4

I have several projects in my solution:

  • Logan.Web.DBContext defines the DbContext for the database and builds the data model
  • Logan.Web.Objects defines the classes that will represent the tables in the database
  • Logan.Web.Data defines the data layer that the application will use
  • LoganMVC is the actual MVC website

Obviously I don't want the MVC website to know too much about the database so I have no links between it and the Objects/DBContext projects. Instead, the Data project acts as a "middle-man" between them and contains all the CRUD functionality.

The problem I'm having with this structure is that, to show anything on the Views, the Models need to know the properties for the data as defined in the Objects classes.

I'm not sure how to expose them without referencing the Objects project in the MVC project, but it is my understanding that this would not be good practice. Instead, I'd prefer, if at all possible, to expose them through the data layer, but I also can't figure out how to do that in any way that makes sense.

I've posted all the code for most of these projects as such currently exists on pastebin:

http://pastebin.com/eFahpGzE

  • DBContext namespace starts on line 1
  • DBObjects namespace starts on line 141
  • Data namespace starts on line 185

What's the best way to expose the properties of the classes in Logan.Web.Objects so that they can be used in LoganMVC given the structure defined here?

  • 2
    It sounds like you need a service layer. But it also sounds like you might be over-architecting this. Loose-coupling is a guideline, not a mandate; if you need the data, then you need it. – Robert Harvey Jun 25 '14 at 15:24
  • My friend who got me started with this was showing me how to write code that I can reuse through all my projects and he also said I should set up a service layer to use said reusable code... We just never got as far as creating it and I don't know how or what it should do. An example to handle basic CRUD functions would be perfect – Ortund Jun 25 '14 at 15:26
  • 1
    You can already do CRUD through your Data Access Layer anyway. My suggestion is to focus on methods that do things, like CreateCheckingAccount() and TransferMoney(). – Robert Harvey Jun 25 '14 at 15:27
  • You typically expose methods from the Model to access the DB, and Model would be the only layer that would talk to the DB. That way, rest of the app is isolated from the changes in the DB structure. View talks to the Model to get the required data and renders it. Controller talks to the Model to make appropriate changes to the data. – Omer Iqbal Jun 25 '14 at 15:47
  • This project is meant to be a blogging platform so no need for things like that. The Data layer is handling the CRUD but thats useless right now because I don't know how to pass values into the MVC project – Ortund Jun 25 '14 at 15:50
1

I don't want the MVC website to know too much about the database so I have no links between [the MVC website] and the Objects/DBContext projects

The problem I'm having with this structure is that, to show anything on the Views, the [MVC] Models need to know the properties for the data as defined in the Objects classes.

This is a contradiction. You're intentionally not referencing the Objects project in the MVC project, yet you're expecting to be able to use the Objects classes (and their properties) in the MVC project.

It's one or the other. You can't have your cake and eat it. Or, more appropriately, you can't not reference your project and then reference its classes.


You've separated your entities from your MVC project, but you're not offering a substitute. If your MVC project can't use your entities; then what should it use?

Note: I'm generally apprehensive of overengineering. I can agree with the commenters that mention you may be overengineering this. But for the sake of your question, it's clear that you want this separation, so I'll answer as such.

Your Data project should not be sending object classes back to the MVC project, but rather DTOs (which can be mirror copies of the entity classes, that's not inherently wrong to do).

A simple example:

In the Objects project:

public class Person 
{
    public string Name { get; set; }
}

In the Data project:

public class PersonDto
{
    public string Name { get; set; }
}

Also in the Data project, at the repository level:

public PersonDto GetPersonById(int personId)
{
    Objects.Person person = myContext.People.Single(p => p.Id == personId);

    Data.PersonDto personDto = new PersonDTO();
    personDto.Name = person.Name;

    return personDto;
}

This way, the Person object never leaves the Data project. The MVC project is not aware that Person exists, it only knows that PersonDto exists.

Extra mentions:

  • AutoMapper is a commonly used library to automate the mapping between an entity and its equivalent DTO class. If the properties have the same name and type, you can very quickly have Automapper convert one to the other automatically. If the names are different, you need to specify the mapping of course.
  • The code here is heavily simplified for the sake of example.
  • In case you want to do this, separating the Data (business query logic) and DTO (entity clones) doesn't really make sense. All projects I've seen keep these two together, since they are so closely tied together
    • DTOs exist specifically because your Data class exists as an abstraction layer. Having one without the other is a bit silly.
    • You separated your DbContext from your entities. That is a bit different, there is a meaningful distinction there (e.g. if you support both database and XML file storage with the same entity classes). However, a Data layer is generally intended as a unique layer, which therefore also has unique DTO objects.
  • Personally, I really dislike using return types from libraries (Objects) to external callers (MVC), specifically because it requires the external caller (MVC) to also reference the library (Objects). More often than not, having to do so defeats the purpose of creating the abstraction in the first place.
    • Exceptions can be made for libraries that are used on all levels for other purposes, e.g. using NLog if you wish to have logging on all application levels. But you'll generally not really be returning NLog objects/types from one project to the other.
0

What you might want to look at is Command Query Responsibility Segregation. The basis of the idea is that interactions with your information would be through commands (CRUD operations can also be modeled as commands. For the displaying you'll then create very specific models that can just be displayed as is. So if I understood correctly in this case you can drive the CRUD operations from the MVC project making calls to the Data project. You can then add a Logan.Web.Models project that you can use to do data reads which will allow you to build object representations that won't expose CRUD functionality and would merely serve as read-only objects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.