我创建了一个通用的Repository类,所有其他Repository类都继承自它。这很好,因为这意味着几乎所有的基础设施只需要一次性地完成即可应用于所有的Repository。我在这里提供了对我所说的内容的全面说明(链接),但以下是我的GenericRepository的代码(为简洁起见,已删除部分代码):
正如您所见,我有一个Create方法和一个Update方法。拥有一个“CreateOrUpdate”方法会非常方便,这样我就不必每次保存到数据库时手动检查现有对象。
我的Entity Framework中的每个对象都有一个“Id”,但是在此处的挑战是GenericRepository使用“T”。
现在,在那个相当长的介绍之后,来回答我的具体问题。
如何为我的GenericRepository创建一个通用的CreateOrUpdate方法?
更新:
在Marcin的回复之后,我在我的GenericRepository中实现了以下通用方法。在我测试它是否按预期工作之前,需要一些时间,但它看起来非常有前途。
public abstract class GenericRepository<T> : IGenericRepository<T> where T : class, new()
{
private IMyDbContext _myDbContext;
public GenericRepository(IMyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
protected IMyDbContext Context
{
get
{
return _myDbContext;
}
}
public IQueryable<T> AsQueryable()
{
IQueryable<T> query = Context.Set<T>();
return query;
}
public virtual void Create(T entity)
{
Context.Set<T>().Add(entity);
}
public virtual void Update(T entity)
{
Context.Entry(entity).State = System.Data.EntityState.Modified;
}
}
正如您所见,我有一个Create方法和一个Update方法。拥有一个“CreateOrUpdate”方法会非常方便,这样我就不必每次保存到数据库时手动检查现有对象。
我的Entity Framework中的每个对象都有一个“Id”,但是在此处的挑战是GenericRepository使用“T”。
现在,在那个相当长的介绍之后,来回答我的具体问题。
如何为我的GenericRepository创建一个通用的CreateOrUpdate方法?
更新:
在Marcin的回复之后,我在我的GenericRepository中实现了以下通用方法。在我测试它是否按预期工作之前,需要一些时间,但它看起来非常有前途。
public virtual bool Exists(Guid id)
{
return Context.Set<T>().Any(t => t.Id == id);
}
public virtual void CreateOrUpdate(T entity)
{
if (Exists(entity.Id))
{
var oldEntity = GetSingle(entity.Id);
Context.Entry(oldEntity).CurrentValues.SetValues(entity);
Update(oldEntity);
}
else
{
Create(entity);
}
}
上述代码在更新时需要至少3次往返数据库。我相信它可以被优化,但这并不是这个问题的重点。
这个问题更好地处理了这个主题: 一个带有相同键的对象已经存在于ObjectStateManager中。ObjectStateManager无法跟踪具有相同键的多个对象
entity.ID == default(Guid)
)。此外,如果您打算使用延迟加载,您可能希望确保始终创建代理。请参考以下示例:https://dev59.com/P3LYa4cB1Zd3GeqPYoIC#16811976 - Colin