我正在开发一个应用程序,其中我的数据库架构与我的域模型不匹配,并且对数据库架构的修改不在我的控制之下。因此,我最终在我的存储库调用中进行了大量映射,并且我有许多具体的存储库来处理与数据库之间的映射(首先使用实体框架数据库)。我正在寻找的是一种基于域实体对象类型调用我的存储库的优雅方式。到目前为止,领域模型本身仍然非常贫乏,因为我们仍在定义业务规则的过程中。
我在其他地方看到了一个示例(不记得链接),其中存储库调用是通过静态属性通过域实体传递的,但我不知道这是否会出现线程问题或是否违反任何域模型原则,尤其是如果我们决定在未来实施 DI/IoC。
这是我到目前为止的一个例子。为简洁起见,我简化了对数据库的映射调用,因为实际应用程序中的映射更加复杂。
存储库示例:
public interface IRepository<T>
{
T GetById(int id);
void Save(T entity);
}
public abstract class RepositoryFactory<T> : IRepository<T>
{
protected MyDbContext db;
protected int userId;
protected RepositoryFactory()
{
this.db = new MyDbContext();
this.userId = WebSecurity.GetCurrentUser().UserId;
}
public abstract T GetById(int id);
public abstract void Save(T entity);
}
public class CustomerRepository : RepositoryFactory<Customer>
{
public override void Save(Customer customer)
{
var entity = db.customers.FirstOrDefault(p => p.customerid == customer.Id && p.users.userid == userId);
if (entity == null) return; // TODO: Add error trapping
// Mapping (lots of reshaping happening here)
entity.customername = customer.Name;
entity.customeraddress = customer.Address;
// ...
// Save changes to DB
db.Entry(entity).State = EntityState.Modified;
db.SaveChanges();
}
public override Customer GetById(int id)
{
var entity = db.customers.FirstOrDefault(p => p.customerid == id && p.users.userid == userId);
if (entity == null) return null; // TODO: Add error trapping
return new Customer
{
Name = entity.customername,
Address = entity.customeraddress,
// ...
};
}
}
域实体示例:
public class Entity { public int Id { get; set; } }
public class Customer : Entity
{
public string Name { get; set; }
public string Address { get; set; }
// Does this violate any domain principles?
public static IRepository<Customer> Repository
{
get { return new CustomerRepository(); }
}
}
使用此代码,我可以从我的控制器执行以下操作:
Customer customer = Customer.Repository.GetById(id);
代替:
IRepository<Customer> repo = new CustomerRepository();
Customer customer = repo.GetById(id);
对于我的问题,这似乎是一个非常优雅的解决方案,而且它还使我无需在我的控制器 (MVC) 中包含 Repository 命名空间。如果这闻起来很有趣并且有更好的方法来处理这个问题,我很乐意学习。我能想到的唯一另一件事是创建一个单独的 crud 服务来处理我的存储库调用,但我想为此我需要一个字典或哈希表来将我的具体存储库映射到我的域模型对象,这似乎会成为维护的噩梦。