的EntityKey和ApplyPropertyChanges() [英] EntityKey and ApplyPropertyChanges()

查看:117
本文介绍了的EntityKey和ApplyPropertyChanges()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要设定一个EntityObject的的EntityKey。我知道它的类型和其id值。我不希望不必要地查询数据库。

I need to set an EntityObject's EntityKey. I know its type and its id value. I don't want to query the database unnecessarily.

本作品...

//
// 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 ApplyPropertyChanges() line fails with this exception:

该ObjectStateManager不
  包含具有一个ObjectStateEntry
  参考类型的对象
  Sample.Models.Department。

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

这两个EntityKeys是相等的。为什么code的第二块失败?我怎样才能解决这个问题?

The two EntityKeys are equal. Why does the second block of code fail? How can I fix it?

推荐答案

您code的第二块失败的原因是因为EF找不到在ObjectStateManager对象 - 即它从数据库对象时,它使他们在状态管理器,因此它可以跟踪他们 - 这是类似标识映射模式。尽管有一个的EntityKey,你的对象是不在状态管理器,以便EF是无法坚持的变化。你可以解决这个问题通过将物体进入状态经理youself,但你必须有点偷偷摸摸的了。

The reason your second block of code fails is because EF can't find the object in the ObjectStateManager - i.e. when it pulls objects from the db it puts them in the state manager so it can track them - this is similar to the Identity Map pattern. Despite having an EntityKey, your object isn't in the state manager so EF is unable to persist the changes. You can get around this by putting the object into the state manager youself but you have be a bit sneaky about it.

本作品:

[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。

... but it's not very clean. Basically this is attaching an 'empty' object with just an entity key, accepting all changes and then calling ApplyPropertyChanges with the actual real updated values.

下面是一个扩展方法包裹起来同样的事情 - 这应该为任何有使用主键的单一数据库列工作。调用该方法的唯一有趣的是,你需要告诉它如何通过委托作为第二个参数的扩展方法来找到问题的关键属性:

Here's the same thing wrapped up in an extension method - this should work for anything that has uses a single db column for the primary key. The only interesting part of calling the method is that you need to tell it how to find the key property via a delegate as the second argument to the extension method:

[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的操作方法:)

As the extension method is calling AcceptAllChanges, you'd need to be careful about calling this if you are doing updates on multiple entities at once - you could easily 'lose' updates if you aren't careful. Hence this approach is only really suitable for simple update scenarios - e.g. a lot of MVC action methods :)

这篇关于的EntityKey和ApplyPropertyChanges()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆