2013-06-24 213 views
2

编辑

我录了一段截屏与我的问题,你可以找到它here,请看,如果你有时间。实体框架创建重复实体

我有下面的代码应该执行AddOrUpdate功能,而是所有现有的记录被重新创建,因此我有几个纽约,几个美国的。我从客户端传输EntityState,以便如果客户端上的数据发生更改,客户端会相应地更新EntityState属性并将其发送到服务器。

[HttpPost, HttpGet, HttpPut] 
    public HttpResponseMessage SaveRecord(RecordViewModel record) 
    { 
     var model = Mapper.Map<Record>(record); 

     if (!ModelState.IsValid) 
     { 
      return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); 
     } 

     db.Attach(model); 

     try 
     { 
      db.SaveChanges(); 
     } 
     catch (DbUpdateConcurrencyException ex) 
     { 
      return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex); 
     } 

     return Request.CreateResponse(HttpStatusCode.OK, Mapper.Map<RecordViewModel>(model)); 
    } 

我附加实体具有以下功能

public void AttachAndMarkAs<T>(T entity, EntityState state, Func<T, object> id) where T : class 
    { 
     var entry = Entry(entity); 

     if (entry.State == EntityState.Detached) 
     { 
      var set = Set<T>(); 

      T attachedEntity = set.Find(id(entity)); 

      if (attachedEntity != null) 
      { 
       var attachedEntry = Entry(attachedEntity); 

       if (state != EntityState.Unchanged) 
       { 
        attachedEntry.CurrentValues.SetValues(entity); 
        attachedEntry.State = state; 
       } 
      } 
      else 
      { 
       entry.State = state; 
      } 
     } 
    } 

这是通过以下的人转述:

public void Attach(City entity) 
    { 
     if (entity != null) 
     { 
      Attach(entity.Country); 

      AttachAndMarkAs(entity, entity.EntityState ?? EntityState.Added, instance => instance.Id); 
     } 
    } 

    public void Attach(Country entity) 
    { 
     if (entity != null) 
     { 
      AttachAndMarkAs(entity, entity.EntityState ?? EntityState.Added, instance => instance.Id); 
     } 
    } 

我不明白这部分的代码添加手柄实体而不是更新它们,因为EntityState值是正确的...

+1

如果你说“我不知道哪一部分呢?”不那意味着你从别处复制了代码? –

+0

您的EntityState为空,因此它始终将其视为Add。 – Maess

+0

您是否设置了一些断点并查看发生了什么? – MaxSC

回答

3

如果哟你正在使用简单的int作为你的id,你可以使用下面的方法。

public abstract class BaseEntity 
{ 
    public int Id { get; set; } 
} 

public void AddOrUpdate<T> (T entity) where T : BaseEntity 
{ 
    if(entity.Id > 0){ 
     Entry(entity).State = EntityState.Modified; 
    } 
    else 
    { 
     Set<T>().Add(entity); 
    } 
} 

// 

var model = Mapper.Map<Record>(record); 
db.AddOrUpdate(model); 
db.SaveChanges(); 
+0

嗯,让我试试... – Lu4

+0

真的很奇怪,问题依然存在... – Lu4

+0

我想我已经得到它,我有外部的实体,其中包含儿童的实体。子项目是创建的“独立”属性 – Lu4

2

你需要注意的实体框架是如何处理孩子/引用的实体,当你编程更改父实体的状态。

看看这个article,它总结了事情在许多不同情况下的工作方式。

在下面的例子中,你可能会认为,所有被引用的实体将被自动设置为Modifiied

using (var context = new BloggingContext()) 
{ 
    context.Entry(existingBlog).State = EntityState.Modified; 
    // Do some more work... 
    context.SaveChanges(); 
} 

但实际上,他们不会。 书面上的文章:

如果您有需要注明修改时间,你应该 单独设置的状态这些实体的多个实体。

最后,这里是你需要处理AddOrUpdate具体情况的方式,当你PrimaryKeyInt

using (var context = new BloggingContext()) 
{ 
    context.Entry(blog).State = blog.BlogId == 0 ? EntityState.Added : EntityState.Modified; 

    context.SaveChanges(); 
} 
+0

您的示例如何显示引用的实体保持不变的状态? –

+0

对不起,我不清楚,我已经更新了我的答案。我从[那里](http://msdn.microsoft.com/en-us/data/jj592676.aspx)举了一个例子,告知开发人员有关“EntityState”修改的真实行为。 – MaxSC

+0

感谢您的链接,真的很有帮助 – Lu4