C#实体框架动态代理-维护相同记录的单独对象实例,并且仅跟踪其中的更改?

时间:2019-06-26 23:45:00

标签: c# entity-framework

长话短说,我有一些复杂的对象(由数不清的子对象[由数据库首先生成的多个EF对象组成],集合和属性组成),并且在编辑操作期间,我想手动比较单独的对象实例值,或将我的对象的某些部分与数据库中的值以及excel电子表格上传中的其他值重用。问题在于实体框架似乎在两个单独的对象实例之间引用相同的动态代理?

例如:

Car myCarOld = dbContext.Cars.Where(c=>c.id == id).FirstOrDefault();
Car myCar = dbContext.Cars.Where(c=>c.id == id).FirstOrDefault();
string oldMake = myCarOld.Make;
myCar.Make = "Toyota"; // Why is this line also updating myCarOld?  Shouldn't they be separate object instances with their own unique values?

if(myCarOld.Make != myCar.Make){
   Console.WriteLine("Hey, they don't match which is what I expect.");
}else{
   Console.WriteLine("Hey, they do match in value, huh?");
}

输出“嘿,它们的值确实匹配,是吗?”。如何防止这种情况发生?我只想跟踪myCar对象中的更改,而不会弄乱myCarOld中的旧原始值。我可以在对对象进行更改之前对对象进行深克隆,但这在我的情况下不起作用,因为我使用的某些基本MVC对象(如SelectListItem不可序列化)。

我阅读了一些有关分离上下文对象context.Entry(personEntity).State = EntityState.Detached;的内容,但是要对自定义对象中的所有EF对象执行此工作似乎需要做很多工作?我什至不确定这是否会对我的情况有所帮助,也不确定我是否正在描述自己想要正确执行的操作。我很困惑。请帮助清除此问题。感谢您的帮助。

Entity Framework and maintaining two instances of entity类似,但是有没有一种方法可以改变查询呢?我只想获取结果并将其作为具有自己唯一值集的单独对象保存。

1 个答案:

答案 0 :(得分:1)

  

我有一些复杂的物体...

  

我可以在对对象进行更改之前对对象进行深克隆,但这在我的情况下不起作用,因为我使用的某些基本MVC对象(如SelectListItem)无法序列化。

简短的回答是SelectListItem之类的东西不属于实体图。如果实体亲戚渴望加载,则深层副本序列化对于跟踪记录的初始状态将是一个不错的选择。

您所看到的是设计使然。如果我有很多汽车,例如列表汽车,那就没什么不同了,然后去:

var car1 = cars[0];
var car2 = cars[0];

,这些指向同一辆车。 EF将检查是否知道汽车ID“ n”,如果不是,它将从数据库加载并返回它。从那时起,它就知道了,因此,如果再次要求输入“ n”,它将返回对同一记录的引用。

除非进行深拷贝克隆,否则请使用单独的DbContext实例:

using (var context = new CarContext())
{
  using (var originalContext = new CarContext())
  {
    var originalCar = originalContext.Cars.Single(x => x.CarId == carId);
    var car = context.Cars.Single(x => x.CarId == carId);

    // Do your thing to Car, reference originalCar for comparisons.

    context.SaveChanges();
    // Do not call originalContext.SaveChanges()
  }
}

成本是从数据库中读取对象的2倍。同样,您不能将引用从originalCar复制到car。即car.Engine = originalCar.Engine之类的东西。由originalContext加载的实体是由originalContext而不是上下文跟踪的。尝试这样做将导致有关已跟踪实体的错误。尝试分离并重新连接还会导致错误或奇怪的行为,例如重复的行或键冲突。