gpt4 book ai didi

c# - EntityKey 和 ApplyPropertyChanges()

转载 作者:太空狗 更新时间:2023-10-29 20:52:32 26 4
gpt4 key购买 nike

我需要设置 EntityObject 的 EntityKey。我知道它的类型和它的 id 值。我不想不必要地查询数据库。

这有效...

//
// POST: /Department/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
Model.EntityKey = (from Department d in db.Department
where d.Id == id
select d).FirstOrDefault().EntityKey;
db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
db.SaveChanges();
return RedirectToAction("Index");
}

这失败了...

//
// POST: /Department/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
String EntitySetName = db.DefaultContainerName + "." + Model.GetType().Name;
Model.EntityKey = new System.Data.EntityKey(EntitySetName, "Id", Model.Id);
db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
db.SaveChanges();
return RedirectToAction("Index");
}

ApplyPropertyChanges() 行因以下异常而失败:

The ObjectStateManager does not contain an ObjectStateEntry with a reference to an object of type 'Sample.Models.Department'.

两个 EntityKey 是相等的。为什么第二个代码块会失败?我该如何解决?

最佳答案

第二个代码块失败的原因是因为 EF 无法在 ObjectStateManager 中找到对象 - 即当它从数据库中提取对象时,它会将它们放入状态管理器中以便它可以跟踪它们 - 这类似于Identity Map图案。尽管有 EntityKey,但您的对象不在状态管理器中,因此 EF 无法保留更改。您可以通过自己将对象放入状态管理器来解决这个问题,但您对此有点偷偷摸摸。

这个有效:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
var entitySetName = db.DefaultContainerName + "." + model.GetType().Name;
var entityKey = new System.Data.EntityKey(entitySetName, "Id", model.Id);

db.Attach(new Department{Id = id, EntityKey = entityKey});
db.AcceptAllChanges();

db.ApplyPropertyChanges(entitySetName, model);
db.SaveChanges();
}

...但它不是很干净。基本上这是附加一个只有实体键的“空”对象,接受所有更改,然后使用实际的实际更新值调用 ApplyPropertyChanges。

这是一个扩展方法中包含的相同内容 - 这应该适用于使用单个 db 列作为主键的任何内容。调用该方法唯一有趣的部分是您需要告诉它如何通过委托(delegate)作为扩展方法的第二个参数来查找关键属性:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
db.ApplyDetachedPropertyChanges(model, x => x.Id);
db.SaveChanges();
}

和扩展方法:

public static class EfExtensions
{
public static void ApplyDetachedPropertyChanges<T>(this ObjectContext db, T entity, Func<T, int> getIdDelegate)
where T : EntityObject
{
var entitySetName = db.DefaultContainerName + "." + entity.GetType().Name;
var id = getIdDelegate(entity);
var entityKey = new EntityKey(entitySetName, "Id", id);

db.Attach(new Department {Id = id, EntityKey = entityKey});
db.AcceptAllChanges();

db.ApplyPropertyChanges(entitySetName, entity);
}
}

由于扩展方法正在调用 AcceptAllChanges,因此如果同时对多个实体进行更新,则在调用此方法时需要小心——如果不小心,很容易“丢失”更新。因此这种方法只适用于简单的更新场景——例如很多 MVC 操作方法:)

关于c# - EntityKey 和 ApplyPropertyChanges(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/898260/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com