.NET 8 EF Core中如何避免同类型实体变量值自动复制?
解决EF Core中实体对象引用复制导致的属性同步修改问题
问题原因
你遇到的问题本质是C#引用类型的特性:Fold_Trans是类(引用类型),执行var NewRow = CurRow;时并没有创建新的对象实例,只是把CurRow的内存引用赋值给了NewRow,两者指向同一个对象。因此修改任意一个变量的属性,都会同步影响另一个。
解决方案
需要创建CurRow的独立对象副本,以下是几种可行的实现方式:
1. 手动创建新实例并复制属性
适合属性较少的场景,明确控制复制的属性:
var CurRow = db.Fold_Trans.AsNoTracking().First(x => x.ID == Id); List<Fold_Trans> LsFoldTrans = [CurRow]; // ... 保留原有的数值计算代码 ... // 替换原有的var NewRow = CurRow; var NewRow = new Fold_Trans { // 复制CurRow的基础属性 Piece = CurRow.Piece, MainPiece = CurRow.MainPiece, // 按需复制其他属性(如创建时间、关联字段等) ID = 0 // 新实体ID设为0,标识为新增记录 }; // 修改CurRow的属性(不会影响NewRow) CurRow.Gmtrs = BalMtrs; CurRow.Weight = BalWt; // 修改NewRow的属性(不会影响CurRow) int ExCn = 1; NewRow.Piece = $"{CurRow.Piece}-TP{ExCn}"; NewRow.MainPiece = $"{CurRow.MainPiece}-TP{ExCn}"; NewRow.Gmtrs = TpMtrs; NewRow.Weight = TpWt; LsFoldTrans.Add(NewRow); db.Fold_Trans.AddUpdateOrDeleteCommRange(LsFoldTrans, x => x.ID == Id); db.SaveChanges();
2. 使用MemberwiseClone实现浅拷贝
MemberwiseClone是.NET内置的浅拷贝方法,会创建新实例并复制所有值类型属性,对于简单实体(无复杂导航属性)足够高效:
// 创建CurRow的浅拷贝副本 var NewRow = (Fold_Trans)CurRow.MemberwiseClone(); NewRow.ID = 0; // 重置ID为新增状态 // 后续属性修改逻辑同第一种方法
注意:如果实体包含引用类型的导航属性,浅拷贝会共享这些属性的引用,若需要完全独立的副本,需手动处理导航属性的克隆(深拷贝)。
3. 使用映射工具简化复制(推荐)
如果项目中频繁需要复制实体对象,可使用AutoMapper这类工具自动映射属性,减少手动复制的代码量:
// 全局配置(可放在Program.cs或Startup.cs) var mapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap<Fold_Trans, Fold_Trans>(); }); var mapper = mapperConfig.CreateMapper(); // 复制对象 var NewRow = mapper.Map<Fold_Trans>(CurRow); NewRow.ID = 0;
项目中避免此类问题的规范
- 明确引用类型与值类型的区别:团队内部统一认知,类是引用类型,赋值传递的是内存引用而非对象副本。
- 封装实体克隆方法:在实体类中添加
Clone方法,统一复制逻辑:
使用时直接调用:public class Fold_Trans { // 实体属性... public Fold_Trans CloneAsNew() { var clone = (Fold_Trans)MemberwiseClone(); clone.ID = 0; // 默认重置ID为新增状态 // 若有导航属性,在此处处理深拷贝 return clone; } }var NewRow = CurRow.CloneAsNew(); - 代码审查重点关注:在涉及实体修改、新增的代码中,检查是否存在直接赋值引用的情况。
- 禁止直接引用赋值:约定所有实体复制操作必须通过克隆、手动实例化或映射工具完成,杜绝
var newObj = oldObj;这类写法。
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

