Zac*_*son 6 .net c# asp.net-mvc entity-framework
我需要设置一个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");
}
Run Code Online (Sandbox Code Playgroud)
这失败了......
//
// 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");
}
Run Code Online (Sandbox Code Playgroud)
该ApplyPropertyChanges()线路出现故障与此异常:
ObjectStateManager不包含ObjectStateEntry,其中引用了"Sample.Models.Department"类型的对象.
两个EntityKeys是平等的.为什么第二块代码失败?我该如何解决?
你的第二个代码块失败的原因是因为EF无法在ObjectStateManager中找到对象 - 即当它从db中提取对象时它将它们放在状态管理器中以便它可以跟踪它们 - 这类似于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();
}
Run Code Online (Sandbox Code Playgroud)
......但它不是很干净.基本上,这是仅使用实体键附加"空"对象,接受所有更改,然后使用实际的实际更新值调用ApplyPropertyChanges.
这是在扩展方法中包含的相同内容 - 这应该适用于对主键使用单个db列的任何内容.调用该方法唯一有趣的部分是你需要告诉它如何通过委托找到key属性作为扩展方法的第二个参数:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
db.ApplyDetachedPropertyChanges(model, x => x.Id);
db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
和扩展方法:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
由于扩展方法调用AcceptAllChanges,如果您同时对多个实体进行更新,则需要小心调用此方法 - 如果您不小心,可能很容易"丢失"更新.因此,这种方法只适用于简单的更新场景 - 例如很多MVC动作方法:)
| 归档时间: |
|
| 查看次数: |
13081 次 |
| 最近记录: |