Repository Pattern without an ORM

后端 未结 3 1268
清酒与你
清酒与你 2021-02-05 05:46

I am using repository pattern in a .NET C# application that does not use an ORM. However the issue I am having is how to fill One-to-many List properties of an entity. e.g. if a

3条回答
  •  孤城傲影
    2021-02-05 06:21

    can I do DDD without ORM ?

    Yes, but an ORM simplifies things.

    To be honest I think your problem isn't to do with whether you need an ORM or not - it's that you are thinking too much about the data rather than behaviour which is the key for success with DDD. In terms of the data model, most entities will have associations to most another entities in some form, and from this perspective you could traverse all around the model. This is what it looks like with your customer and orders and perhaps why you think you need lazy loading. But you need to use aggregates to break these relationships up into behavioural groups.

    For example why have you modelled the customer aggregate to have a list of order? If the answer is "because a customer can have orders" then I'm not sure you're in the mindset of DDD.

    What behaviour is there that requires the customer to have a list of orders? When you give more thought to the behaviour of your domain (i.e. what data is required at what point) you can model your aggregates based around use cases and things become much clearer and much easier as you are only change tracking for a small set of objects in the aggregate boundary.

    I suspect that Customer should be a separate aggregate without a list of orders, and Order should be an aggregate with a list of order lines. If you need to perform operations on each order for a customer then use orderRepository.GetOrdersForCustomer(customerID); make your changes then use orderRespository.Save(order);

    Regarding change tracking without an ORM there are various ways you can do this, for example the order aggregate could raise events that the order repository is listening to for deleted order lines. These could then be deleted when the unit of work completed. Or a slightly less elegant way is to maintain deleted lists, i.e. order.DeletedOrderLines which your repository can obviously read.

    To Summarise:

    • I think you need to think more about behaviour than data
    • ORM's make life easier for change tracking, but you can do it without one and you can definitely do DDD without one.

    EDIT in response to comment:

    I don't think I'd implement lazy loading for order lines. What operations are you likely to perform on the order without needing the order lines? Not many I suspect.

    However, I'm not one to be confined to the 'rules' of DDD when it doesn't seem to make sense, so... If in the unlikely scenario that there are a number of operations performed on the order object that didn't require the order lines to be populated AND there are often a large number of order lines associated to an order (both would have to be true for me to consider it an issue) then I'd do this:

    Have this private field in the order object:

    private Func> _lazilyGetOrderLines;
    

    Which would be passed by the order repository to the order on creation:

    Order order = new Order(this.GetOrderLines);
    

    Where this is a private method on the OrderRepository:

    private IList GetOrderLines(Guid orderId)
    {
        //DAL Code here
    
    }
    

    Then in the order lines property could look like:

    public IEnumberable OrderLines
    { 
        get 
        {
             if (_orderLines == null)
                _orderLines = _lazilyGetOrderLines(this.OrderId);
    
             return _orderLines;
        }
    }
    

    Edit 2

    I've found this blog post which has a similar solution to mine but slightly more elegant:

    http://thinkbeforecoding.com/post/2009/02/07/Lazy-load-and-persistence-ignorance

提交回复
热议问题