2

编辑

我已经录制了一个关于我的问题的截屏视频,你可以在这里找到它,如果你有时间请看看。

我有以下代码应该执行 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 值是正确的......

4

2 回答 2

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();
于 2013-06-24T20:41:52.673 回答
3

当您以编程方式更改父实体的状态时,您需要注意实体框架如何处理子/引用实体。

看看这篇文章,它总结了许多不同情况下的工作方式。

在下面的示例中,您可能认为所有引用的实体将自动设置为Modifiied

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

但实际上,他们不会。正如文章中所写:

如果您有多个实体需要标记为已修改,则应分别为每个实体设置状态。

最后,这是您在 is 时处理特定情况所需的AddOrUpdate方式:PrimaryKeyInt

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

   context.SaveChanges();
}
于 2013-06-25T08:06:29.083 回答