首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EntityKey和ApplyPropertyChanges()

EntityKey和ApplyPropertyChanges()
EN

Stack Overflow用户
提问于 2009-05-22 14:50:03
回答 5查看 13.3K关注 0票数 6

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

这很管用..。

代码语言:javascript
复制
//
// 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");
}

这失败了..。

代码语言:javascript
复制
//
// 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()行将失败:

ObjectStateManager不包含引用“Sample.Models.Department”类型对象的ObjectStateEntry。

这两个EntityKeys是相等的。为什么第二个代码块会失败?我怎么才能修好它?

EN

回答 5

Stack Overflow用户

发布于 2009-05-22 15:06:43

第二个代码块失败的原因是因为EF无法在ObjectStateManager中找到对象--也就是说,当它从db中提取对象时,它将它们放在状态管理器中以便跟踪它们--这类似于身份图模式。尽管有一个EntityKey,但您的对象不在状态管理器中,因此EF无法持久化更改。您可以通过将对象放入状态管理器来绕过这一问题,但您对此已经有点偷偷摸摸了。

这样做是可行的:

代码语言:javascript
复制
[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列的任何内容。调用该方法的唯一有趣部分是,您需要告诉它如何通过委托找到键属性,作为扩展方法的第二个参数:

代码语言:javascript
复制
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
  db.ApplyDetachedPropertyChanges(model, x => x.Id);
  db.SaveChanges();
}

扩展方法:

代码语言:javascript
复制
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操作方法:)

票数 9
EN

Stack Overflow用户

发布于 2009-11-26 10:42:45

代码语言:javascript
复制
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;

        T newEntity = Activator.CreateInstance<T>();
        newEntity.EntityKey = db.CreateEntityKey(entitySetName, entity);

        Type t = typeof(T);
        foreach(EntityKeyMember keyMember in newEntity.EntityKey.EntityKeyValues) {
            PropertyInfo p = t.GetProperty(keyMember.Key);
            p.SetValue(newEntity, keyMember.Value, null);
        }

        db.Attach(newEntity);
        //db.AcceptAllChanges();

        db.ApplyPropertyChanges(entitySetName, entity);
    }
}
票数 4
EN

Stack Overflow用户

发布于 2010-07-29 07:31:48

试着使用下面的代码,并让我知道它是否适合你。

代码语言:javascript
复制
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    using (var context =  new EntityContext())
    {
        try
        {
            Object entity = null;
            IEnumerable<KeyValuePair<string, object>> entityKeyValues =
                new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("DepartmentID", id) };

            // Create the  key for a specific SalesOrderHeader object. 
            EntityKey key = new EntityKey("EntityContext.Deparment",   
                                                                   entityKeyValues);

            // Get the object from the context or the persisted store by its key.
            if (context.TryGetObjectByKey(key, out entity))
            {
               context.ApplyPropertyChanges(key.EntitySetName, Model);
               context.SaveChanges();
            }
            else
            {
               // log message if we need
               //"An object with this key could not be found." 
            }                
        }
        catch (EntitySqlException ex)
        {
           // log message
        }
    }
 }       
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/898260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档