0

I've been trying to develop an N-Layered design with a WinForms application using Entity Framework.

Is the below sample flow correct for saving a new record in an n-layered design using Entity Framework?

  1. Presentation Layer

    A) UI performs light screen input data validations. Then UI converts view model to DTO and passes it to the Application Layer.

  2. Application Layer

    A) Application Layer sends DTO to Domain Model in Domain Layer

  3. Domain Layer

    A) Validate incoming DTO values for compliant business rules before creating new instance of Domain Model SoftwareRequest Entity.

    B) If all values are validated, then create new instance of Domain Model SoftwareRequest Entity.

    C) Exit to return control to Application Layer

  4. Application Layer

    A) Call Infrastructure Layer SoftwareRequest Repository and pass in the new Domain Model SoftwareRequest Entity which was provided by the Domain Model

  5. Infrastructure Layer Data Access

    A) SoftwareRequest Repository receives new Domain Model SoftwareRequest Entity from Application Layer.

    B) Add new Domain Model SoftwareRequest Entity to Entity Framework DBContext - context.SoftwareRequests.Add(NewDomainModelEntity)

    C) Save new entity - context.SaveChanges()

    D) Exit to return control back to Application Layer

  6. Application Layer

    A) Convert results of save operation to DTO

    B) Exit to return control back to UI with DTO containing results of adding new SoftwareRequest

  7. UI

    A) Convert received DTO to View Model

    B) Display View Model data to screen showing results of adding a new software request

--------- Below information added on 2/22/2016 at 6:49am PST ---------

Dependency Summary:

Presentation Layer - References Application Layer to make requests - References Domain Layer only for the purpose of working with interfaces describing DTO's which will be sent from the UI or received from the Application Layer

Application Layer - References Domain Layer interfaces describing DTO's. Also uses interface definitions for Domain Model Entities so it can convert entity responses from the Infrastructure Layer to DTO's which are returned to the UI. A reference to the Infrastructure Layer Data Access is also here so repositories can be access to perform CRUD operations after the involved Domain Model Entities have been validated for rules and values by the Domain Layer.

Domain Layer - Has no references to any layers above or below. Has no dependency injected services from any layer. This includes no tasks involving CRUD with infrastructure repositories. All requests such as for validation of rules receive DTOs containing all the necessary information to carry out requested domain tasks.

Infrastructure Layer Data Access - References Domain Layer interfaces describing Domain Model Entities which are used to perform Entity Framework operations in repositories (i.e. CRUD operations). Also references Domain Layer for definitions of interfaces for repositories which are implemented here in the Infrastructure Layer data access. DTOs are not used in this layer. This layer typically responds with Domain Model Entities to the Application Layer. The Application Layer converts all Domain Model Entity responses (i.e. IEnumerable) to DTOs which are sent back to the UI.

Robertcode
  • 781
  • 7
  • 21
  • Can you post a description of the dependencies between your projects ? It looks as though your Domain has a reference to the Application layer - which is not recommended - or some classes are declared in the wrong layer. – guillaume31 Feb 22 '16 at 09:33
  • If it works and it produces the expected results it is "correct". There's really not much more we can say about this. We can argue about assembly dependencies (f.e. Domain -> Data Access, seemingly), but then we enter the opinion-based arena. – Gert Arnold Feb 22 '16 at 10:02
  • Can't qualify as an answer but there is a decent course on Pluralsight where they explain DDD with examples using EF. You might be interested in it. – Alexey Zimarev Feb 22 '16 at 13:51
  • Guillaume31, I've updated the description with a dependency summary. Gert Arnold, the above flow does work as expected. Alexey Zimarev, I'll also check the newest DDD video on Pluralsight released this year. I already saw the older one for enterprise apps. The above flow is not a pure DDD solution; I was not looking for one. It is an adaptation created to work with .NET, Entity Framework and WinForms. Thanks everyone for the input. – Robertcode Feb 22 '16 at 15:01

1 Answers1

1

Based on your description, I suspect that the DTO types are declared in the Domain layer. It's not really where they belong because DTO's might change as the client changes and we don't want modify the Domain every time the client evolves. Also, DTO's can contain use case-level fields such as confirmPassword which are of no interest to the Domain.

Another thing is that the Application Layer is supposed to control the business transaction and not just be a facade to the Domain.

Here's how I would adjust it :

  1. Application Layer

    A) Application Layer maps DTO to new entity, either by calling its constructor or a Factory if construction is complicated

  2. Domain Layer

    A) In entity constructor or Factory, validate the values that the entity is initialized with (non-nullability, value ranges, dependent arguments etc.)

    B) Exit to return control to Application Layer

...

  1. Infrastructure Layer Data Access

    A) SoftwareRequest Repository receives new Domain Model SoftwareRequest Entity from Application Layer.

    B) Add new Domain Model SoftwareRequest Entity to Entity Framework DBContext - context.SoftwareRequests.Add(NewDomainModelEntity)

    C) Exit to return control back to Application Layer

  2. Application Layer

    A) Save new entity - context.SaveChanges()

    B) Convert results of save operation to DTO

Note that as you move business transaction control from the Infrastructure layer to the Application layer, you might have to introduce a new abstraction - typically Unit of Work - to abstract yourself from Entity Framework's DbContext.

Edit : a sample to illustrate this

/* Application layer */

public class SoftwareRequestDTO
{
    public string Name { get; set; }
    // your other SoftwareRequest data here
}

public class SoftwareRequestApplicationService
{
    // constructor etc...

    public void CreateSoftwareRequest(SoftwareRequestDTO dto)
    {
        using (var transaction = new BusinessTransaction()) // UoW or whatever - can also be constructor injected into the service
        {
            var softwareRequest = new SoftwareRequest(dto.Name);
            _softwareRequestRepository.Add(softwareRequest);
            transaction.Complete();
        }
    }
}

/* Domain layer */

public class SoftwareRequest
{
    public SoftwareRequest(string name)
    {
        // validation/guard clause
        if (name == null)
        {
            throw new DomainException("SoftwareRequest name cannot be null");
        }
        // your assignments here
    }
}
guillaume31
  • 12,725
  • 28
  • 43
  • Requests originating from the UI passed to the Application Layer then to Domain contain input data as DTOs. The Domain does not need to reference any other layer to do validations for rules and values. However, if I move the DTO definitions outside the Domain then I will need to reference that layer in order to resolve incoming requests. Right now my Domain does not need to reference any other layer. The idea to put them in the Domain came from one of Bob Taber's videos titled: Architecting the Domain Layer. The video marker is 14:26 His website is www.learnvisualstudio.net. – Robertcode Feb 24 '16 at 01:47
  • The full URL to the video by Bob Taber is this URL: https://members.learnvisualstudio.net/videos/aa-ad_09-creating-a-stubbed-persistence-class-and-data-transfer-object-class/ In the site navigate as follows: Application Architecture Fundamentals then AA-AD_09 – Creating a Stubbed Persistence Class and Data Transfer Object Class – Robertcode Feb 24 '16 at 01:53
  • @Robertcode Please read my entire answer. The domain has no business (pun !) dealing with DTO's. DTO's declared in Domain is equally problematic as Domain referencing Application. – guillaume31 Feb 24 '16 at 08:58
  • @Robertcode DTO stands for `Data Transfer Object`, it is a simple structure used to reflect data transferred between tiers. Clients of the Domain layer don't *transfer data to the Domain.* They instantiate domain entities and value objects using primitive types. – guillaume31 Feb 24 '16 at 09:32
  • When my user submits a request from the UI the content of what was on the screen is converted to a DTO and passed to the Application Layer then to the Domain where the values are read and used to validate and instantiate new entities. If you are not passing in a DTO for the Domain to do this then what are you passing in that originated from the UI? – Robertcode Feb 24 '16 at 15:42
  • You are passing scalar values, primitive types. See my edit. – guillaume31 Feb 24 '16 at 16:01
  • I have created a new question to try and get an example of your recommendation here: http://stackoverflow.com/questions/35608067/what-format-is-data-in-when-passed-to-a-domain-layer-for-validations Please provide an example I can use (i.e. data structure?). Thank you for your assistance. – Robertcode Feb 24 '16 at 16:58
  • Well I did provide an example. The Application Service cracks the DTO open and takes any values in it (ints, strings, dates, etc.) and passes them as arguments to the domain to create a new Entity or perform a domain operation on an existing Entity. I don't know how to explain this better. – guillaume31 Feb 24 '16 at 17:08
  • On line `123` here you can see another example of an Application Service calling a Domain entity giving it plain primitive values (although the input doesn't come to the Service in the form of a DTO in that case) http://gorodinski.com/blog/2012/04/14/services-in-domain-driven-design-ddd/ – guillaume31 Feb 24 '16 at 17:10