我是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(以及域模型)时的最佳实践是什么,应该由应用程序的功能(用例)驱动?在您的解释中,请在上面的示例中随意使用和更改代码。
答案 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));
}
}