EFCore Bulk Insert 没有更新预期的数据库生成的 IDs

问题描述 投票:0回答:1

我正在使用 EFCore.BulkExtensions lib 版本 6.7.0 和 EntityFrameworkCore 6.0.13,试图重现文档中解释的以下行为:

using (var transaction = context.Database.BeginTransaction())
{
    context.BulkInsert(entities, new BulkConfig { SetOutputIdentity = true });
    foreach (var entity in entities) {
        foreach (var subEntity in entity.ItemHistories) {
            subEntity.ItemId = entity.ItemId; // sets FK to match its linked PK that was generated in DB
        }
        subEntities.AddRange(entity.ItemHistories);
    }
    context.BulkInsert(subEntities);
    transaction.Commit();
}

entity.ItemId
应该用数据库生成的PK更新。

我无法用下面的代码重现它,结果总是:

[ENTITY ID]: 0

using (var transaction = dbContext.Database.BeginTransaction())
{
    var entities = entitiesEnumerable.ToList();

    foreach (var e in entities)
    {
        e.Id = default;
    }

    var bulkConfig = new BulkConfig
    {
        SetOutputIdentity = true
    };
    await dbContext.BulkInsertAsync(entities, bulkConfig);
    foreach (var e in entities)
    {
        _logger.LogWarning($"[ENTITY ID]: {e.Id}");
    }
    transaction.Commit();
}

我的实体有如下属性作为PK,底层数据库是SQL Server:

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
c# entity-framework .net-core efcore.bulkextensions
1个回答
0
投票

问题似乎与批量插入操作后如何访问生成的身份有关。带有 SetOutputIdentity 选项的 BulkInsert 操作将在插入操作完成后使用生成的标识值更新实体的 Id 属性。

但是,在您的代码中,您在批量插入操作后立即迭代实体并访问 Id 属性。此时 Id 值可能尚未更新,这就是为什么您始终将 0 作为值的原因。

要解决此问题,您可以尝试等待批量插入操作完成,然后再访问更新后的 Id 值。您可以使用 await dbContext.BulkInsertAsync(entities, bulkConfig) 方法等待批量插入操作完成,然后遍历实体以访问更新后的 Id 值。这是一个例子:

using (var transaction = dbContext.Database.BeginTransaction())
{
    var entities = entitiesEnumerable.ToList();

    foreach (var e in entities)
    {
        e.Id = default;
    }

    var bulkConfig = new BulkConfig
    {
        SetOutputIdentity = true
    };
    await dbContext.BulkInsertAsync(entities, bulkConfig);
    await dbContext.SaveChangesAsync(); // Wait for the bulk insert operation to complete

    foreach (var e in entities)
    {
        _logger.LogWarning($"[ENTITY ID]: {e.Id}");
    }
    transaction.Commit();
}

通过在批量插入操作之后调用 await dbContext.SaveChangesAsync(),您可以确保在访问它们之前更新 Id 值。

© www.soinside.com 2019 - 2024. All rights reserved.