0

I am new to EF, Code First and DDD and still in the learning process, so let's say I have simple domain like this

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; }
}

After domain is defined the next step is to create DbContext derived class and my question is how should it look like? What is a context class definition driven by? Is it by the use cases of the final application?

For example, looking at the domain above we can see that given the Customer instance we can access any child object. So is it then enough to make the context class contains only Customers property look like this:

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

With this I can browse customers from my app and then select one to see details and orders history etc... Looks good for now.

Now let's say I want following feature in my application: - list last 10 orders in store (no matter who was the customer) - list all orders with specific product in it

I guess that this data can be pulled from the current context right? Eg. last 10 orders:

        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();
        }

And getting all orders that contain product with 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();

        }

(note I didn't test these queries so not sure if they work but they describe my general idea)

So I guess this would work but I am wondering is this the right path. Queries can get pretty complex here and it would probably be easier if I add say Orders and Products to the DbContext: public class MyContext : DbContext { public DbSet Customers { get; set; } public DbSet Orders { get; set; } public DbSet Products { get; set; } }

On the other hand I am not sure if I should add orders since they can already be retrieved from the Customer etc...

To sum it up, what are best practices when defining DbContext (and domain model for that matter) and should that be driven by the features (use cases) of the application? Feel free to use and change code in my example above in your explanation.

matori82
  • 3,669
  • 9
  • 42
  • 64

1 Answers1

2

Consider protected setters for your properties. Otherwise you could end up with 'data entities' rather then a proper domain model.

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));
    }
}
jgauffin
  • 99,844
  • 45
  • 235
  • 372
Krijn
  • 41
  • 2