我已经根据我的问题录制了一个截屏视频,您可以找到它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值是正确的......
答案 0 :(得分: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();
答案 1 :(得分:2)
当您以编程方式更改父实体的状态时,需要注意实体框架如何处理子实体/引用实体。
看看这个article,它总结了许多不同情况下的工作原理。
在下面的示例中,您可能会认为所有引用的实体都会自动设置为Modifiied
:
using (var context = new BloggingContext())
{
context.Entry(existingBlog).State = EntityState.Modified;
// Do some more work...
context.SaveChanges();
}
但实际上,他们不会。 如文章所述:
如果您有多个需要标记为已修改的实体 应该单独为每个实体设置状态。
最后,当AddOrUpdate
为PrimaryKey
时,您需要处理Int
特定案例的方式:
using (var context = new BloggingContext())
{
context.Entry(blog).State = blog.BlogId == 0 ? EntityState.Added : EntityState.Modified;
context.SaveChanges();
}