最近,我们的EF架构迁移到了这一点。我正在寻找关于如何最好地改变它(或不)的建议。
我们有一个"Data“项目,其中包含我们的DataModel.EDMX文件和一个返回entities对象的Context.cs类:
public static DataModelEntities getContext() {
return new DataModelEntities();
}然后,我们创建一个"Business“项目,其中几乎包含EF生成的类的副本。例如,如果我们有一个customer表,我们创建一个CustomerBO类来保存属性:
public class CustomerBO {
public int customerId {get;set;}
public string firstName {get;set;}
public string lastName {get;set;}
public int orderCount {get;set;}
}从理论上讲,我们可以使用EF创建的Customer类,但我们没有这样做,因为如果我们最终序列化它并通过网络传递它,它通常包含许多额外的东西。
在我们的CustomerBO类中,我们有用于检索/保存数据的方法。例如,getCustomerList方法:
public static List<CustomerBO> getCustomers() {
using (var context = Context.getContext()) {
var lst = from c in context.Customers
select c;
// Wrap the EF results to a List<Customer>
return toCustomerList(lst);
}
}
/// Wraps a queryable object to a List<Customer>
private static List<CustomerBO> toCustomerList(IEnumerable<Customer> queryCustomerData) {
var data = from c in queryCustomerData
select new CustomerBO() {
customerId = c.customerId,
firstName = c.firstName,
lastName = c.lastName,
orderCount = c.CustomerOrders.Count()
};
return data.ToList();
}我们总是确保使用toCustomerList方法将所有数据返回给图形用户界面。它向我们保证将设置任何自定义属性,例如orderCount,并且不需要开发人员记住将这些自定义属性添加到主EF查询中。
总体而言,设计是可靠的,解决了我们多年来遇到的许多问题。然而,有一个特别的问题领域困扰着我。我们称我们的层为"Business“,但我们在其中有一些”查询“逻辑。有没有一种更好的方法来架构它,使其与既定的模式保持一致,同时仍然达到相同的结果?
发布于 2010-12-08 05:10:04
你的设计看起来相当不错。
我要说的一点是,尽量不要使用静态辅助方法进行数据检索,也不要把它们放在DTO类中(例如CustomerBO)。
为什么不在你的数据项目中创建一个仓库呢?
称之为CustomerRepository,,它的职责将是将业务查询转换为EF查询,并将结果投影到DTO中。
这种方式容易得多-你保持你的DTO很好很薄,他们不应该有任何逻辑。
或者,如果您了解延迟执行和延迟加载的风险,您可以从存储库返回IQueryable<T>,并从业务层返回具体的集合(例如ICollection<T>) -这是我们为实现最大灵活性所做的事情。所有的逻辑(查询/业务)都在我们的业务/服务层。
你的“业务”层有查询逻辑没什么问题--我们也这样做。我们在业务层构建查询并将其传递到存储库。
你能想到的唯一一种模式是CQRS --将“查询”和“命令”分开。
然而,这是一个相当繁琐/复杂的架构。
我认为将DAL代码抽象到Repository中就足够了。
HTH。
编辑
下面是一个非常简单的IQueryable<T>存储库示例:
CustomerRepository
public class CustomerRepository
{
private MyDataContext _ctx;
public CustomerRepository(MyDataContext ctx)
{
this._ctx = ctx;
}
public IQueryable<Order> FindOrders()
{
return _ctx.Orders;
}
}CustomerDomainService
public class CustomerDomainService
{
public ICollection<Order> GetOrdersForCustomer(int customerId)
{
// You should in reality use interfaces and dependency injection here..
CustomerRepository repo = new CustomerRepository(new MyContext());
var orders = repo.FindOrders().Where(x => x.CustomerId == customerId).ToList();
}
}正如我所说的,在使用IQueryable存储库时要非常小心。仅将查询推迟到您的域服务,而不是稍后。此外,只有您的域服务应该引用存储库。
因此,您的演示文稿请求来自域服务的数据,域服务根据存储库进行查询并返回结果。
发布于 2010-12-08 01:02:03
我猜你可以使用EF实体(如果你说你的版本几乎是重复的),并且只用你需要的额外功能来创建它们的部分类,比如通过网络发送它们的序列化。我看不出有什么问题。每次更新您的edmx时,您的部分类将保持不变。
https://stackoverflow.com/questions/4379135
复制相似问题