首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数据架构

数据架构
EN

Stack Overflow用户
提问于 2010-12-08 00:40:03
回答 2查看 323关注 0票数 1

最近,我们的EF架构迁移到了这一点。我正在寻找关于如何最好地改变它(或不)的建议。

我们有一个"Data“项目,其中包含我们的DataModel.EDMX文件和一个返回entities对象的Context.cs类:

代码语言:javascript
复制
public static DataModelEntities getContext() {        
    return new DataModelEntities();
}

然后,我们创建一个"Business“项目,其中几乎包含EF生成的类的副本。例如,如果我们有一个customer表,我们创建一个CustomerBO类来保存属性:

代码语言:javascript
复制
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方法:

代码语言:javascript
复制
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“,但我们在其中有一些”查询“逻辑。有没有一种更好的方法来架构它,使其与既定的模式保持一致,同时仍然达到相同的结果?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-12-08 05:10:04

你的设计看起来相当不错。

我要说的一点是,尽量不要使用静态辅助方法进行数据检索,也不要把它们放在DTO类中(例如CustomerBO)。

为什么不在你的数据项目中创建一个仓库呢?

称之为CustomerRepository,,它的职责将是将业务查询转换为EF查询,并将结果投影到DTO中。

这种方式容易得多-你保持你的DTO很好很薄,他们不应该有任何逻辑。

或者,如果您了解延迟执行和延迟加载的风险,您可以从存储库返回IQueryable<T>,并从业务层返回具体的集合(例如ICollection<T>) -这是我们为实现最大灵活性所做的事情。所有的逻辑(查询/业务)都在我们的业务/服务层。

你的“业务”层有查询逻辑没什么问题--我们也这样做。我们在业务层构建查询并将其传递到存储库。

你能想到的唯一一种模式是CQRS --将“查询”和“命令”分开。

然而,这是一个相当繁琐/复杂的架构。

我认为将DAL代码抽象到Repository中就足够了。

HTH。

编辑

下面是一个非常简单的IQueryable<T>存储库示例:

CustomerRepository

代码语言:javascript
复制
public class CustomerRepository
{
   private MyDataContext _ctx;

   public CustomerRepository(MyDataContext ctx)
   {
      this._ctx = ctx;
   }

   public IQueryable<Order> FindOrders()
   {
      return _ctx.Orders;
   }
}

CustomerDomainService

代码语言:javascript
复制
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存储库时要非常小心。仅将查询推迟到您的域服务,而不是稍后。此外,只有您的域服务应该引用存储库。

因此,您的演示文稿请求来自域服务的数据,域服务根据存储库进行查询并返回结果。

票数 1
EN

Stack Overflow用户

发布于 2010-12-08 01:02:03

我猜你可以使用EF实体(如果你说你的版本几乎是重复的),并且只用你需要的额外功能来创建它们的部分类,比如通过网络发送它们的序列化。我看不出有什么问题。每次更新您的edmx时,您的部分类将保持不变。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4379135

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档