EF 4.2 Code First and DDD Design Concerns

前端 未结 2 1287
梦谈多话
梦谈多话 2020-12-24 08:39

I have several concerns when trying to do DDD development with EF 4.2 (or EF 4.1) code first. I\'ve done some extensive research but haven\'t come up with concrete answers f

2条回答
  •  有刺的猬
    2020-12-24 09:28

    On 1: I'm not all that familiar with EF but using the code-first/convention based mapping approach, I'd assume it's not too hard to map POCOs with getters and setters (even keeping that "DbContext with DbSet properties" class in another project shouldn't be that hard). I would not consider the POCOs to be the Aggregate Root. Rather they represent "the state inside an aggregate you want to persist". An example below:

    // This is what gets persisted
    public class TrainStationState {
      public Guid Id { get; set; }
      public string FullName { get; set; }
      public double Latitude { get; set; }
      public double Longitude { get; set; }
    
      // ... more state here
    }
    
    // This is what you work with
    public class TrainStation : IExpose { 
      TrainStationState _state;
    
      public TrainStation(TrainStationState state) {
        _state = state;
        //You can also copy into member variables
        //the state that's required to make this
        //object work (think memento pattern).
        //Alternatively you could have a parameter-less
        //constructor and an explicit method
        //to restore/install state.
      }
    
      TrainStationState IExpose.GetState() {
        return _state;
        //Again, nothing stopping you from
        //assembling this "state object"
        //manually.
      }
    
      public void IncludeInRoute(TrainRoute route) {
        route.AddStation(_state.Id, _state.Latitude, _state.Longitude);
      }
    }
    

    Now, with regard to aggregate life-cycle, there are two main scenario's:

    1. Creating a new aggregate: You could use a factory, factory method, builder, constructor, ... whatever fits your needs. When you need to persist the aggregate, query for its state and persist it (typically this code doesn't reside inside your domain and is pretty generic).
    2. Retrieving an existing aggregate: You could use a repository, a dao, ... whatever fits your needs. It's important to understand that what you are retrieving from persistent storage is a state POCO, which you need to inject into a pristine aggregate (or use it to populate it's private members). This all happens behind the repository/DAO facade. Don't muddle your call-sites with this generic behavior.

    On 2: Several things come to mind. Here's a list:

    1. Aggregate Roots are consistency boundaries. What consistency requirements do you see between an Organization and an Employee?
    2. Organization COULD act as a factory of Employee, without mutating the state of Organization.
    3. "Ownership" is not what aggregates are about.
    4. Aggregate Roots generally have methods that create entities within the aggregate. This makes sense because the roots are responsible for enforcing consistency within the aggregate.

    On 3: Assign identifiers from the outside, get over it, move on. That does not imply exposing them, though (only in the state POCO).

提交回复
热议问题