如何在使用带有DDD方法的EF Code First时正确定义DbContext派生类?

时间:2013-05-27 00:07:42

标签: entity-framework domain-driven-design code-first domain-model

我是EF,Code First和DDD的新手并且还处于学习过程中,所以让我说我有这样的简单域名

public class Customer
{
    public string Name { get; set; }
    public string Address { get; set; }

    public List<Order> Orders { get; set; }
}

public class Order
{
    public DateTime OrderDate { get; set; }
    public List<LineItem> LineItems { get; set; }
}

public class LineItem
{
    public Product Product { get; set; }
    public int Quantity { get; set; }
}

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

定义域后,下一步是创建DbContext派生类,我的问题是它应该是什么样子?什么是上下文类定义?是最终申请的用例吗?

例如,查看上面的域,我们可以看到,给定Customer实例,我们可以访问任何子对象。那么就足以使上下文类只包含Customers属性如下所示:

class MyContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
}

有了这个,我可以从我的应用程序浏览客户,然后选择一个查看详细信息和订单历史记录等...现在看起来不错。

现在让我说我想在我的应用程序中使用以下功能: - 列出商店的最后10个订单(无论谁是客户) - 列出包含特定产品的所有订单

我猜这个数据可以从当前的上下文中拉出来吗?例如。最后10个订单:

        using (var context = new MyContext())
        {
            var lastTenOrders = context.Customers.Include("Orders")
                                             .Select(customer => customer.Orders)
                                             .SelectMany(orderList => orderList)
                                             .OrderByDescending(order => order.OrderDate)
                                             .Take(10)
                                             .ToList();
        }

获取包含Id = 5的产品的所有订单:

        using (var context = new MyContext())
        {
            int productId = 5;

            var lastTenOrders = context.Customers.Include("Orders")
                                             .Select(customer => customer.Orders)
                                             .SelectMany(orderList => orderList)
                                             .Where(order => order.LineItems.Where(i => i.Product.Id == productId).Any())
                                             .ToList();

        }

(注意我没有测试这些查询,因此不确定它们是否有效但是它们描述了我的总体想法)

所以我想这会有效,但我想知道这是正确的道路。这里的查询可能变得相当复杂,如果我将说明订单和产品添加到DbContext中可能会更容易:     public class MyContext:DbContext     {         public DbSet Customers {get;组; }         公共DbSet订单{get;组; }         public DbSet Products {get;组; }     }

另一方面,我不确定是否应该添加订单,因为它们已经可以从客户等处获取...

总结一下,定义DbContext(以及域模型)时的最佳实践是什么,应该由应用程序的功能(用例)驱动?在您的解释中,请在上面的示例中随意使用和更改代码。

1 个答案:

答案 0 :(得分:2)

考虑属性的受保护的setter。 否则,你最终可能会得到数据实体&#39;而不是一个适当的领域模型。

public class Customer
{
    public string Address { get; protected set; }

    public MoveTo(string newAddress)
    {
        if (newAddress == null) throw new ArgumentNullException("newAddress");
        // and other address sanity checks..

        Address = newAddress;
        DomainEvent.Publish(new CustomerMoved(CustomerNumber, newAddress));
    }
}