我仍然有一些與存儲庫模式混淆。我想要使用這種模式的主要原因是爲了避免從域中調用EF 4.1特定的數據訪問操作。我寧願從IRepository接口調用通用的CRUD操作。這將使測試變得更容易,如果將來我必須更改數據訪問框架,我將能夠在不重構大量代碼的情況下進行測試。存儲庫模式與實體框架4.1和父/子關係
這裏是我的情況爲例:
我在數據庫中有3個表:Group
,Person
和GroupPersonMap
。 GroupPersonMap
是一個鏈接表,只包含Group
和Person
主鍵。我使用VS 2010設計器創建了3張表的EF模型。 EF足夠聰明地假設GroupPersonMap
是一個鏈接表,所以它不會在設計器中顯示它。我想使用現有的域對象而不是EF的生成類,因此我關閉了模型的代碼生成。
我的EF模型匹配現有的類如下:
public class Group
{
public int GroupId { get; set; }
public string Name { get; set; }
public virtual ICollection<Person> People { get; set; }
}
public class Person
{
public int PersonId {get; set; }
public string FirstName { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
我有一個通用的存儲庫接口,像這樣:
public interface IRepository<T> where T: class
{
IQueryable<T> GetAll();
T Add(T entity);
T Update(T entity);
void Delete(T entity);
void Save()
}
和通用EF庫:
public class EF4Repository<T> : IRepository<T> where T: class
{
public DbContext Context { get; private set; }
private DbSet<T> _dbSet;
public EF4Repository(string connectionString)
{
Context = new DbContext(connectionString);
_dbSet = Context.Set<T>();
}
public EF4Repository(DbContext context)
{
Context = context;
_dbSet = Context.Set<T>();
}
public IQueryable<T> GetAll()
{
// code
}
public T Insert(T entity)
{
// code
}
public T Update(T entity)
{
Context.Entry(entity).State = System.Data.EntityState.Modified;
Context.SaveChanges();
}
public void Delete(T entity)
{
// code
}
public void Save()
{
// code
}
}
現在假設我只想將現有的Group
映射到現有的Person
。我會做一些類似如下:
EFRepository<Group> groupRepository = new EFRepository<Group>("name=connString");
EFRepository<Person> personRepository = new EFRepository<Person>("name=connString");
var group = groupRepository.GetAll().Where(g => g.GroupId == 5).First();
var person = personRepository.GetAll().Where(p => p.PersonId == 2).First();
group.People.Add(person);
groupRepository.Update(group);
但是,這並不工作,因爲EF認爲Person
是新的,並會嘗試重新INSERT
的Person
到數據庫中,這將導致一個主鍵約束錯誤。我必須使用DbSet
的Attach
方法來告訴EF Person
已經存在於數據庫中,因此只需在GroupPersonMap
表中創建Group
和Person
之間的映射。
因此,爲了連接Person
的方面,我現在必須的Attach
方法添加到我的IRepository:
public interface IRepository<T> where T: class
{
// existing methods
T Attach(T entity);
}
要解決主鍵約束錯誤:
EFRepository<Group> groupRepository = new EFRepository<Group>("name=connString");
EFRepository<Person> personRepository = new EFRepository<Person>(groupRepository.Context);
var group = groupRepository.GetAll().Where(g => g.GroupId == 5).First();
var person = personRepository.GetAll().Where(p => p.PersonId == 2).First();
personRepository.Attach(person);
group.People.Add(person);
groupRepository.Update(group);
固定。現在,我必須處理另一個問題,其中每次創建組/人員映射時,都會在數據庫中更新Group
。這是因爲在我的EFRepository.Update()
方法中,實體狀態明確設置爲Modified'. I must set the Group's state to
未更改so the
組表未被修改。
爲了解決這個問題,我必須添加某種Update
過載到我的IRepository不更新根實體,或Group
的,在這種情況下:
public interface IRepository<T> where T: class
{
// existing methods
T Update(T entity, bool updateRootEntity);
}
更新方法的EF4 implentation看起來會是像這樣:
T Update(T entity, bool updateRootEntity)
{
if (updateRootEntity)
Context.Entry(entity).State = System.Data.EntityState.Modified;
else
Context.Entry(entity).State = System.Data.EntityState.Unchanged;
Context.SaveChanges();
}
我的問題是:我接近這個正確的方式?當我開始使用EF和存儲庫模式時,My Repository開始看起來以EF爲中心。感謝您閱讀這篇長文章
+1很好的答案 –
+1非常豐富的 –
+1爲實體框架+工作單元。存儲庫需要共享相同的dbcontext。我敢打賭,這是我的問題。 – Jhayes2118