Given an application that involves, say, Companies, I might have a Company class. I will have a data access layer that populates a List <Company>. However, there will be times (such as displaying a search result) where I only need to display the Company name, telephone and postcode properties, and it seems to me that populating the entire Company object with all its properties seems wasteful.
What would be the right way to go about this in terms of a DDD design? Would I create View specific classes, such as a CompanySearchResult object which only exposes the properties I'm interested in displaying?
That sounds like a reasonable approach to me.
Later on, if the customer comes to you asking for your SearchResult to display something unrelated to the Company model - something crazy like the number of nearby ice cream shops you'll have a much easier time appending this to your CompanySearchResult than your domain object.
This is what is typically known as a "view model" or a Data Transfer Object. You may not want your view to have access to the entire data tree exposed by your domain model. Especially if exposing your domain model means that your view will have to dig deep into your object graph to pull the data it needs, a View Model can make alot of sense to simplify working with the model objects. In your case, if you are simply pulling direct properties off of the model object, it would make sense if you want to hide the extraneous data not needed by the rest of your domain model.
The approach you suggest can quickly increase the number of DAO:s you need to create and become a maintenance nightmare. The approach that several ORMs take is to proxy the data access, so your data access layer will return a list of interfaces, and the database call will be postponed until you invoke the data accessor, for instance
list.getCompany(1).getName()
. This is call lazy loading. You will still need to make a trade off between making many small or fewer big queries. This type of tasks is one of the strengths of ORMs, you can usually ask your ORM to prefetch parts of the object graph which you think will be used, and leave out other parts.
I use a crumble of the entity attributes. For example:
// interface for "ID" attribute of Company entity
public interface ICompany_ID {
Guid CompanyID{get;set;}
}
// interface for "Name" attribute of Company entity
public interace ICompany_Name {
string Name{get;set;}
}
// interface for "Logo" attribute of Company entity
public interface ICompany_Logo {
byte[] Logo{get;set;}
}
// interface for all attributes of Company entity
public interface ICompany : ICompany_ID, ICompany_Name, ICompany_Logo { }
// base class for classes based on Company entity
public abstract class CompanyBase : ICompany_ID {
// implementation of ICompany_ID interface
}
// class for all attributes of Company entity
public class Company : ICompany {
// implementation of ICompany interface (all attributes)
}
// class for Company name lookup
public class CompanyNameLookup : CompanyBase, ICompany_Name {
// implementation of ICompany_Name interfade
}
This crumble allow me to work with different attributes of different entities and all is type-safe.
however, your data-layer must support this scenario.
The next way is dynamic creation of lookup classes, but it is much more complex. On the other side, it is much more flexible.
EDIT:
Then the selection can be for example:
var companies = (from c in db.Table<ICompany>()
order by c.Name
select new CompanyNameLookup { ID = c.ID, Name = c.Name }
).ToList();
or for danymicly created types:
var companies = (from c in db.Table<ICompany>()
order by c.Name
select DynamicTypeFactory.New<ICompany_ID>( c.Id ).And<ICompany_Name>( c.Name ).Create()
).ToList();
The DynamicTypeFactory is class with static method New and fluent interface for danymic creation classes at run-time.
Related
I have a project with a repository, a service layer, using EF6 and code-first POCOs. In the CustomerRepository, I am doing several projection queries that return objects.
I understand that the code-first POCO's are what would be considered "Domain Models", but if I were to do a projection query into a different model, what is that model considered? An example of this would be the CustomerOrderStats. Is that still a Domain Model, or should that be considered a DTO model?
Example
Object returned from Repository:
public class CustomerOrderStats
{
public string Name { get; set; }
public int Count { get; set; }
}
Query in the Repository
public CustomerOrderStats GetCustomerOrderStats(Guid customerGuid)
{
return customers
.Where(c => c.Guid == customerGuid)
.Select(new CustomerOrderStats
{
Name = c.Name,
Count = c.Orders.Count()
};
}
It could be either one, really. The definition of a model vs. a DTO isn't really a matter of how you organize any given framework, but rather what that object represents in the domain. If it has rich functionality or business logic or is an active part of the actual business process, it's probably a model. If, on the other hand, it's just a container of properties to move values from one place to another, it's probably a DTO.
The key here is whether the object is an active part of the business process. And a good rule of thumb here is often the name of the object.
Is it a name that non-technical business team members understand?
Is it a term they use to describe what the business does? (Even a very small part of the business)
Does it carry a meaning in the industry in general?
A DTO is generally something that exists for purely technical reasons. Component A needs to send data to Component B, but that operation is a technical one and not a business one. Data just needs to be, well, transferred. As a piece of the system, it's essentially built "from the bottom up" because it satisfies a low-level technical need.
A model describes a part of the business. It could be an element on a chart which defines the business process in non-technical terms, or an encapsulation of a business concept. As a piece of the system, it's essentially built "from the top down" because it is described generally by the business and then implemented specifically to meet that need.
I have a general difference of opinion on an architectural design and even though stackoverflow should not be used to ask for opinions I would like to ask for pros and cons of both approaches that I will describe below:
Details:
- C# application
- SQL Server database
- Using Entity Framework
- And we need to decide what objects we are going to use to store our information and use all throughout the application
Scenario 1:
We will use the Entity Framework entities to pass all around through our application, for example the object should be used to store all information, we pass it around to the BL and eventually our WepApi will take this entity and return the value. No DTOs nor POCOs.
If the database schema changes, we update the entity and modify in all classes where it is used.
Scenario 2:
We create an intermediate class - call it a DTO or call it a POCO - to hold all information that is required by the application. There is an intermediate step of taking the information stored in the entity and populated into the POCO but we keep all EF code within the data access and not across all layers.
What are the pros and cons of each one?
I would use intermediate classes, i.e. POCO instead of EF entities.
The only advantage I see to directly use EF entities is that it's less code to write...
Advantages to use POCO instead:
You only expose the data your application actually needs
Basically, say you have some GetUsers business method. If you just want the list of users to populate a grid (i.e. you need their ID, name, first name for example), you could just write something like that:
public IEnumerable<SimpleUser> GetUsers()
{
return this.DbContext
.Users
.Select(z => new SimpleUser
{
ID = z.ID,
Name = z.Name,
FirstName = z.FirstName
})
.ToList();
}
It is crystal clear what your method actually returns.
Now imagine instead, it returned a full User entity with all the navigation properties and internal stuff you do not want to expose (such as the Password field)...
It really simplify the job of the person that consumes your services
It's even more obvious for Create like business methods. You certainly don't want to use a User entity as parameter, it would be awfully complicated for the consumers of your service to know what properties are actually required...
Imagine the following entity:
public class User
{
public long ID { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string Password { get; set; }
public bool IsDeleted { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<Profile> Profiles { get; set; }
public virtual ICollection<UserEvent> Events { get; set; }
}
Which properties are required for you to consume the void Create(User entity); method?
ID: dunno, maybe it's generated maybe it's not
Name/FirstName: well those should be set
Password: is that a plain-text password, an hashed version? what is it?
IsDeleted/IsActive: should I activate the user myself? Is is done by the business method?
Profiles: hum... how do I affect a profile to a user?
Events: the hell is that??
It forces you to not use lazy loading
Yes, I hate this feature for multiple reasons. Some of them are:
extremely hard to use efficiently. I've seen too much times code that produces thousands of SQL request because the developers didn't know how to properly use lazy loading
extremely hard to manage exceptions. By allowing SQL requests to be executed at any time (i.e. when you lazy load), you delegate the role of managing database exceptions to the upper layer, i.e. the business layer or even the application. A bad habit.
Using POCO forces you to eager-load your entities, much better IMO.
About AutoMapper
AutoMapper is a tool that allows you to automagically convert Entities to POCOs and vice et versa. I do not like it either. See https://stackoverflow.com/a/32459232/870604
I have a counter-question: Why not both?
Consider any arbitrary MVC application. In the model and controller layer you'll generally want to use the EF objects. If you defined them using Code First, you've essentially defined how they are used in your application first and then designed your persistence layer to accurately save the changes you need in your application.
Now consider serving these objects to the View layer. The views may or may not reflect your objects, or an aggregation of your working objects. This often leads to POCOS/DTO's that captures whatever is needed in the view. Another scenario is when you want to publish objects in a web service. Many frameworks provide easy serialization on poco classes in which case you typically either need to 1) annotate your EF classes or 2) make DTO's.
Also be aware that any lazy loading you may have on your EF classes is lost when you use POCOS or if you close your context.
I posted this:
Object depending on another object - when to load its properties
After reading this and researching some more I've come to realize that lazy loading would be ideal for my situation. However, some background info. The class I posted Department gets its properties data from a database (Sql Server 2k5). Its your typical setup:
Front End->BOL->DAL
So I wanted to keep my Department class basically just hold information pertinent to it. I did not / do not want to expose my business object class to this class. So how would I fill my department object without having to make a call to my business object layer.
I think code would help:
public class Employee
{
public int ID { get; set; }
public string FirstName { get; set; }
public Department d { get; set; } //todo: implement lazy load in get.
public Employee(int ID, string FirstName)
{
this.ID = ID;
this.FirstName = FirstName;
}
}
class Department
{
public string DepartmentID { get; set;}
public string CostCenter { get; set; }
public bool hasManager { get; set; }
//more code
//constructor for department
}
And then say my BOL is used to call my DAL to do something like:
//some bol class that simply calls the data access layer class
DAL.GetDepartments("SomeDepartment");
And the DAL does some code to return some data to fill a department object...
However if I lazy load my get property for the department then it would need to know about my BOL so I'd have to add a using statement to include that class as well. That can't be the right way to do this...Any tips or pointers?
If you really want to do lazy loading of components, take a look at some ORM like NHibernate, EF4, etc.
To create your own lazy load solution is not a trivial task and it involves some complex concepts like dynamic proxing, maybe IL generation and other advanced topics.
Anyway, regarding your question on dependencies and use or not use your BOL from your DAL, check if you can apply dependency inversion.
In my current project, almost all my domain business objects have at least two constructors. (1) takes an id for that object, so that it can self-construct, pulling data from the db itself. The other constructor (2) takes the data entity required for that domain object to function. In this way, I can eager load or lazy load, whichever is best at the time.
So, if someone calls your Employee business object Department property, the property could check if it already had that. If not, you could get the DepartmentID from the employee data, instantiate a department, and (store if and) return it. In this way, it's easy to get whatever domain objects you need.
But you still want the eager-loading option there. Let's say you have a Department business object, with an Employees property to return a List(Of Employee). The Employees property would directly get the data from the database, and instantiate each Employee using the data constructor. So you'd have your cool Employee business objects, 80 of them, but with just one data query.
And then to take it up a notch, your objects could accept multi-layer data. For example, you can construct an Employee with an Employee entity from the DAL, that also includes the data for the Department, Supervisor, etc. The "ID" constructor could also get this data from the get-go.
Eventually you'll have some decisions to make about what to pre-load and what to lazy-load. For example, maybe 90% of the time when you construct an Employee, you also need the Department data. Then you might decide to just get the Department data when you construct an employee using the EmployeeID constructor. But the, say, supervisor data is only used 8% of the time. You might decide to always lazy load that.
The simple answer is, obviously, it can't be done. Either you're going to have to let your business objects know about your data layer (make sure to use DI if you go this route) or you can't lazy load from within the business class. A happy medium might be to create a service class that knows about both DAL workings and your business layer and knows how to load and create business objects. Of course, as Juanma stated, ORMs were built to do this kind of thing.
I was under the impression they are all basically the same. Are model objects also the same?
Right now, in my architecture, I have:
class Person
{
public string PersonId;
public string Name;
public string Email;
public static bool IsValidName() { /* logic here */ }
public static bool IsValidEmail() { /* logic here */ }
}
class PersonService
{
private PersonRepository pRepository;
PersonService()
{
pRepository = new PersonRepository();
}
public bool IsExistingEmail(string email)
{
//calls repo method to see if email is in db
}
public Person GetPerson(email)
{
return pRepository.Get(email);
}
public void SavePerson(Person p)
{
if (Person.IsValidEmail(p.Email) && !IsExistingEmail(p.Email)
{
pRepository.Save(p);
}
}
}
class PersonRepository
{
public void Save(Person p)
{
//save to db
}
public Person Get(string email)
{
//get from db
}
public bool IsExistingEmail(string email)
{
//see if email in db
}
}
So which of the above classes are POCO, Domain Object, Model object, entity?
My (non-standard) Layman definitions
POCO - Plain Old %Insert_Your_Language% Object. A type with no logic in it. It just stores data in memory. You'd usually see just auto properties in it, sometimes fields and constructors.
Domain object an instance of a class that is related to your domain. I would probably exclude any satellite or utility objects from domain object, e.g. in most cases, domain objects do not include things like logging, formatting, serialisation, encryption etc - unless you are specifically building a product to log, serialise, format or encrypt respectively.
Model object I think is the same as Domain object. Folks tend to use this interchangeably (I can be wrong)
Entity a class that has id
Repository a class that speaks to a data storage from one side (e.g. a database, a data service or ORM) and to the service, UI, business layer or any other requesting body. It usually hides away all the data-related stuff (like replication, connection pooling, key constraints, transactions etc) and makes it simple to just work with data
Service software that provides some functionality usually via public API. Depending on the layer, it can be for example a RESTful self-contained container, or class that allows you to find a particular instance of needed type.
Original answer
These are terms that are largely used in (Distributed) Domain Driven Design. They are not the same. The term model Object can be used as a synonym to the domain object.
Domain Objects. Objects from the business specific area that represent something meaningful to the domain expert. Domain objects are mostly represented by entities and value objects. Generaly speaking, most objects that live in domain layer contribute to the model and are domain objects.
Entity. An object fundamentally defined not by its attributes, but by a thread of continuity and identity. (Meaning it must have Id)
POCO. A simple object without complicated logic, usually it has just a few properties and is used with ORM or as a Data Transfer Object
class Person - Entity and POCO, instance of this class is Domain Object
class PersonService - Service
class PersonRepository - Repository
basically it comes down to internal logic
Domain objects have internal domain logic for things like validation, etc.
Model is basically a light Domain object, they know about the data they hold but nothing really about how it's going to be used
Entities hold data and have some internal knowledge of where it came from, and where it's going to be saved, updated, etc
POCO holds data and may have some internal knowledge about it's self, things like what is the total value of all the items in a property collection
DTO is the simplest item of all, it just holds data and has no logic
They are all basically used for the same thing, it's just how smart you want them to be
according to your code sample
The Person class would be a domain object or a model, the other 2 are a service and a repository. Domain objects, Pocos, models, dtos, etc. are used like messages, passed from one layer to the next, a service class like PersonService is a layer in the application and the same with the Repository class like PersonRepository. for a good over view take look at http://bob-the-janitor.blogspot.com/2009/07/n-tier-design-revisit-part-1-over-view.html in this case it's talking about using a data entity which is basically a dto
It's more of a connotation of function; a domain object is something that is specific to your logic implementation and might be more complex than a simple POCO; an entity has a connotation to represent something (usually in reference to a persistence medium), and a POCO is just a quick identifier for a class. A model is just a term used to represent an object (usually containing state and usually dealing with the UI or DB).
It's not that there is any functional difference, they're just different terms to more closely describe something. Like the difference between race car, truck, and family sedan. All are automobiles, but each term is more descriptive.
There are already good explainations of Domain and Model in the answers above.
In a Database-Context Entity means Item in a Entity Relationship Model ERD. (i.e. a Row in a Table)
In the Microsoft-Dotnet-EntityFramework-World Entity means an Object that can be loaded from and saved to a database using a Data(Base)Context. Usually an Entity cannot exist without its Data(Base)Context. (Unit-) Testing the business functionality of these classes is difficuilt.
Pocos (Plain Old CommonRuntime Objects) can exist without the PersistenceFramework (EntityFramework or NHibernate) thus they are much easier to test.
The word poco is the adaptaion of pojo (plain old java object) that were created in the java world for the same reason.
A domain object is an entity in the domain layer of your application, eg. an Address class. "Model" means the same thing - an entity in the "Domain Model".
A POCO (plain old CLR object) is an object that has no behaviour (methods) defined, and only contains data (properties). POCO's are generally used as DTOs (data transport objects) to carry data between layers, and the data is then commonly used to populate a domain object/entity.
I am new to both MVC and Entity Framework and I have a question about the right/preferred way to do this.
I have sort of been following the Nerd Dinner MVC application for how I am writing this application. I have a page that has data from a few different places. It shows details that come from a few different tables and also has a dropdown list from a lookup table.
I created a ViewModel class that contains all of this information:
class DetailsViewModel {
public List<Foo> DropdownListData { get; set; }
// comes from table 1
public string Property1 { get; set; }
public string Property2 { get; set; }
public Bar SomeBarObject { get; set; } // comes from table 2
}
In the Nerd Dinner code, their examples is a little too simplistic. The DinnerFormViewModel takes in a single entity: Dinner. Based on the Dinner it creates a SelectList for the countries based on the dinners location.
Because of the simplicity, their data access code is also pretty simple. He has a simple DinnerRepository with a method called GetDinner(). In his action methods he can do simple things like:
Dinner dinner = new Dinner();
// return the view model
return View(new DinnerFormViewModel(dinner));
OR
Dinner dinner = repository.GetDinner(id);
return View(new DinnerFormViewModel(dinner));
My query is a lot more complex than this, pulling from multiple tables...creating an anonymous type:
var query = from a in ctx.Table1
where a.Id == id
select new { a.Property1, a.Property2, a.Foo, a.Bar };
My question is as follows:
What should my repository class look like? Should the repository class return the ViewModel itself? That doesn't seem like the right way to do things, since the ViewModel sort of implies it is being used in a view. Since my query is returning an anonymous object, how do I return that from my repository so I can construct the ViewModel in my controller actions?
While most of the answers are good, I think they are missing an in-between lines part of your question.
First of all, there is no 100% right way to go about it, and I wouldn't get too hung up on the details of the exact pattern to use yet. As your application gets more and more developped you will start seeing what's working and what's not, and figure out how to best change it to work for you and your application. I just got done completely changing the pattern of my Asp.Net MVC backend, mostly because a lot of advice I found wasn't working for what I was trying to do.
That being said, look at your layers by what they are supposed to do. The repository layer is solely meant for adding/removing/and editing data from your data source. It doesn't know how that data is going to be used, and frankly it doesn't care. Therefore, repositories should just return your EF entities.
The part of your question that other seem to be missing is that you need an additional layer in between your controllers and the repositories, usually called the service layer or business layer. This layer contains various classes (however you want to organize them) that get called by controllers. Each of these classes will call the repository to retrieve the desired data, and then convert them into the view models that your controllers will end up using.
This service/business layer is where your business logic goes (and if you think about it, converting an entity into a view model is business logic, as it's defining how your application is actually going to use that data). This means that you don't have to call specific conversion methods or anything. The idea is you tell your service/business layer what you want to do, and it gives you business entities (view models) back, with your controllers having no knowledge of the actual database structure or how the data was retrieved.
The service layer should be the only layer that calls repository classes as well.
You are correct a repository should not return a view model. As changes to your view will cause you to change your data layer.
Your repository should be an aggregate root. If your property1, property2, Foo, Bar are related in some way I would extract a new class to handle this.
public class FooBarDetails
{
public string Property1 {get;set;}
public string Property2 {get;set;}
public Foo Foo {get;set;}
public Bar Bar {get;set;}
}
var details = _repo.GetDetails(detailId);
If Foo and Bar are not related at all it might be an option to introduce a service to compose your FooBarDetails.
FooBarDetails details = _service.GetFooBar(id);
where GetFooBar(int) would look something like this:
_fooRepo.Get(id);
_barRepo.Get(id);
return new FooBarDetails{Foo = foo, Bar = bar, Property1 = "something", Property2 = "something else"};
This all is conjecture since the design of the repository really depends on your domain. Using generic terms makes it hard to develop potential relationships between your objects.
Updated
From the comment if we are dealing with an aggregate root of an Order. An order would have the OrderItem and also the customer that placed the order.
public class Order
{
public List<OrderItem> Items{get; private set;}
public Customer OrderedBy {get; private set;}
//Other stuff
}
public class Customer
{
public List<Orders> Orders{get;set;}
}
Your repo should return a fully hydrated order object.
var order = _rep.Get(orderId);
Since your order has all the information needed I would pass the order directly to the view model.
public class OrderDetailsViewModel
{
public Order Order {get;set;}
public OrderDetailsViewModel(Order order)
{
Order = order;
}
}
Now having a viewmodel with only one item might seem overkill (and it most likely will be at first). If you need to display more items on your view it starts to help.
public class OrderDetailsViewModel
{
public Order Order {get;set;}
public List<Order> SimilarOrders {get;set;}
public OrderDetailsViewModel(Order order, List<Order> similarOrders)
{
Order = order;
SimilarOrders = similarOrders;
}
}
Repository should work only with models not anonymous types and it should only implement CRUD operations. If you need some filtering you can add a service layer for that.
For mapping between ViewModels and Models you can use any of mapping libraries, such as Automapper.
The current answers are very good. I would just point out that you are abusing anonymous types; they should only be used for intermediate transport steps, and never passed to other places in your code (e.g. view model constructors).
My approach would be to inject the view model with all the relevant model classes. E.g. an action method might look like:
var dinner = dinnerRepository.Get(dinnerId);
var bar = barRepository.Get(barId);
var viewModel = new DinnerAndBarFormViewModel(dinner, bar);
return View(viewModel);
I have the same doubt of the poster and I am still not convinced. I personally do not like very much the given advice of limiting the repository to just executing basic CRUD operations. IMHO, performances should always be kept into account when developing a real application, and substituting a SQL outer join with two different queries for master-detail relationships doesn't sound too good to me.
Also, this way the principle that only needed fields should be queried is completely lost: using this approach, we are forced to always retrieve all the fields of all the tables involved, which is simply crazy in non-toy applications!