我創建了一個通用的存儲庫類,所有其他存儲庫類都從中繼承而來。這太好了,因爲這意味着幾乎所有的管道工作都是針對所有的倉庫完成的。我把我在談論here,但這裏什麼是我的GenericRepository代碼的完整解釋(有些代碼爲簡潔,刪除):使用實體框架的非常通用的CreateOrUpdate方法
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;
}
}
正如你看到的,我有一個創建方法和更新方法。有一個「CreateOrUpdate」方法會非常方便,所以我不必每次都必須手動檢查現有對象,以便將某些內容保存到數據庫中。
Entity Framework中的每個對象都有一個「Id」,但這裏面臨的挑戰是GenericRepository與「T」一起工作。
現在,有了相當長的介紹,我的具體問題。
如何爲我的GenericRepository
創建通用CreateOrUpdate
方法?
UPDATE
Marcins響應後,我實現了我的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往返數據庫。我相信它可以被優化,但這不是真正的這個問題的練習。
您將訪問數據庫以確定是否需要插入或更新實體。您只需檢查實體的Id是否爲Guid的默認值。 ('entity.ID == default(Guid)')。如果您打算使用延遲加載,您也可能希望確保始終創建代理。看到這個例子:http://stackoverflow.com/a/16811976/150342 – Colin
一些業務邏輯可能希望在創建時儘早設置一個Guid作爲主鍵,所以我將不得不在數據庫中做一些小的往返處理。否則就是非常好的一點,這在大多數其他情況下都是相關的。謝謝。 –
實際上,每當我嘗試更新時,我的實現失敗,出現以下錯誤:ObjectStateManager中已存在具有相同鍵的對象。 ObjectStateManager不能使用相同的密鑰來跟蹤多個對象。它發生在與現有對象具有相同Guid的新對象時。這與這個問題無關,但只是想讓我知道如果有人想使用這個代碼。 –