EF Core使用BulkMerge时,原实体是否更新?能否获取插入实体?
使用Entity Framework Extensions的BulkMerge获取生成的GUID及合并后数据
核心结论
调用BulkMerge后,原始的recipientsToMerge列表默认不会自动更新插入实体的GUID,但可以通过配置选项实现数据库生成值的回填。
默认行为说明
默认情况下,为了追求批量操作的极致性能,EF Extensions不会自动将数据库生成的GUID(或其他数据库自动生成字段)回写到原列表的实体对象中:
- 对于带ID的更新实体:原列表不会同步数据库中可能的自动更新字段(如
UpdatedTime) - 对于无ID的插入实体:原列表中的实体ID仍为空,不会填充数据库生成的GUID
配置实现回填数据库生成的GUID
要让原列表获取插入实体的数据库生成GUID,需要在BulkMerge时开启OutputIdentity选项,同时确保实体的GUID字段已正确配置为数据库生成:
1. 实体配置(确保GUID字段为数据库生成)
无论是Data Annotation还是Fluent API,都需要标记GUID字段为自动生成:
// Data Annotation方式 public class RecipientEntity { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; set; } public string Name { get; set; } public string LastName { get; set; } // 其他字段... } // 或Fluent API方式(在DbContext的OnModelCreating中) protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<RecipientEntity>() .Property(r => r.Id) .HasDefaultValueSql("NEWID()") // 或NEWSEQUENTIALID() .ValueGeneratedOnAdd(); }
2. 开启OutputIdentity选项调用BulkMerge
var recipientsToMerge = new List<RecipientEntity>{ new RecipientEntity{ Id = Guid.Parse("234134134-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), Name = "...", LastName = "..." }, // 更新实体 new RecipientEntity{ Name = "...", LastName = "..." }, // 插入实体 new RecipientEntity{ Name = "...", LastName = "..." } // 插入实体 }; // 开启OutputIdentity选项 dbContext.BulkMerge(recipientsToMerge, options => { options.OutputIdentity = true; }); // 此时插入的实体已包含数据库生成的GUID foreach (var recipient in recipientsToMerge) { if (recipient.Id != Guid.Empty) { // 可直接使用生成的ID返回至UI Console.WriteLine($"生成的GUID: {recipient.Id}"); } }
注意事项
OutputIdentity仅会回填数据库生成的标识字段(如本例的GUID主键),如果需要同步其他数据库自动更新的字段(如时间戳),可以结合OutputClause自定义配置- 开启该选项会增加少量数据库交互开销,但远低于逐个调用
SaveChanges的成本 - 确保数据库中GUID字段的默认值配置正确(如
NEWID()),否则无法生成有效GUID
内容的提问来源于stack exchange,提问作者Thanasis Ioannidis
相关产品推荐
相关产品推荐

