【问题标题】:Dependency between repositories存储库之间的依赖关系
【发布时间】:2015-03-07 23:02:18
【问题描述】:
我正在使用实体框架和 DDD。
我有以下实体:Person、Customer、Employee
人是抽象的。
客户和员工继承人。
Person 具有对 Person 地址(列表)的引用。
我应该为每种类型创建一个存储库还是只为每种具体类型创建一个存储库? (只是客户和员工)
我是否可以有一个存储库 Person,然后 Customer 和 Employee 存储库在内部依赖它以避免冗余代码? (通过构造函数注入使用DI)
【问题讨论】:
标签:
c#
entity-framework
repository
domain-driven-design
【解决方案1】:
这并不是为了提供完整的应用程序结构,而是为设计使用不同存储库和继承等时可能需要的内容提供良好的基础。
// Model stuff...
public interface IBaseEntity
{
[Key]
int Id { get; set; }
}
public abstract class BaseEntity : IBaseEntity
{
[Key]
public virtual int Id { get; set; }
// Add some extra fields for all Models that use BaseEntity
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[Display(Name = "Last Modified")]
public virtual DateTime LastModified { get; set; }
[ConcurrencyCheck]
[Timestamp]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public virtual byte[] Timestamp { get; set; }
}
public class Person : BaseEntity
{
// Person Model here...
}
public class Employee : Person
{
// Extra Employee Model items here
}
public class Customer : Person
{
// Extra Customer Model items here
}
// End Model stuff
// Repository stuff...
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
T GetById(int? id);
T Add(T entity);
void Update(T entity);
void Delete(T entity);
void Delete(int id);
void Commit(); // To save changes rather than performing a save after each Add/Update/Delete etc.
}
public class EFRepository<T> : IRepository<T> where T : class, IBaseEntity
{
public virtual IQueryable<T> GetAll()
{
return DbSet.AsQueryable<T>();
}
public virtual T GetById(int? id)
{
var item = DbSet.Find(id);
return item;
}
public virtual T Add(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
// SaveChanges() - removed from each DbSet, so can call on all changes in one transaction.
// Using Unit Of Work Pattern. Can still use it here though if wished.
return entity;
}
// And so on for each storage method.
}
public interface IEmployeeRepository: IRepository<Employee>
public interface ICustomerRepository: IRepository<Customer>
public class EmployeeRepository : EFRepository<Employee>, IEmployeeRepository
public class CustomerRepository : EFRepository<Customer>, ICustomerRepository
// End Repository stuff
基本上,您可以通过声明其中几乎没有任何内容的接口和类来添加新模型及其存储库。一切都继承自基本的 crud 功能等。
您只需要在特殊情况下为正在添加的模型添加新方法以从数据库中获取记录 - 例如 FindEmployeeByHairColor(color),所有其他 EF Gets、Finds 等都是相同的,无论类型如何。
这可以变得非常深入,使用服务提供对存储库中核心方法的访问,添加工作单元模式以将多个 DbSet 组合到一个事务中,等等。
但是使用这种类型的布局允许我将我希望使用的特定存储库/服务注入每一层,并将所有逻辑保存在一个类中,该类在使用类似逻辑的所有内容中都可以重复使用。
希望这会有所帮助。
【解决方案2】:
我只会为客户和员工提供存储库。
如果它们之间存在共享逻辑,则将其封装在抽象基类中并让存储库继承自它。
所以你最终会得到这种结构:
public interface ICustomerRepo { }
public interface IEmployeeRepo { }
public abstract class PersonRepoBase<T> { }
public class CustomerRepo : PersonRepoBase<Customer>, ICustomerRepo { }
public class EmployeeRepo : PersonRepoBase<Employee>, IEmployeeRepo { }