I have created a repository that is returning data from my database using Entity Framework and I need to provide this data to my view, but before I do that I need to convert those objects into my domain model.
My schema looks like this:
TABLE Project
Id INT PRIMARY KEY
Name NVARCHAR(100)
TABLE Resource
Id INT PRIMARY KEY
FirstName NVARCHAR(100)
LastName NVARCHAR(100)
TABLE ProjectResources
Project_Id INT PRIMARY KEY -- links to the Project table
Resource_Id INT PRIMARY KEY -- links to the Resource table
I generated an entity model which ended up looking like this:
Project
|
---->ProjectResources
|
---->Resource
I have a repository that returns a Project:
public interface IProjectRepository
{
Project GetProject(int id);
}
And a controller action:
public ActionResult Edit(int id)
{
Project project = projectRepository.GetProject(id);
return View(project);
}
This doesn't seem to work very well when I try and POST this data. I was getting an EntityCollection already initialized error when it was trying to reconstruct the ProjectResources collection.
I think it is smarter to create a domain model that is a little simpler:
public class ProjectEdit
{
public string ProjectName { get; set; }
public List<ProjectResource> Resources { get; set; }
}
public class ProjectResource
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
This seems to be a little nicer since I also don't have the intermediate ProjectResources -> Resource jump. The ProjectResource would have the fields I need. Instead of doing something like:
#foreach( var resource in Model.ProjectResources ) {
#Html.DisplayFor(m => m.Resource.FirstName)
}
I can do:
#foreach( var resoure in Model.Resources ) {
#Html.DisplayFor(m => resource.FirstName);
}
My question is as follows
Should I be returning my domain model from my repository or should that be handled by the controller or some other class in the middle? If it's handled in the controller by something that maps my Project to a ProjectEdit, what would that look like?
My own view is that you shouldn't return anything to your controller or a view that is dependant on the implementation of your repository.
If you're using EF with the POCO Generator, it's reasonable to use those classes for your domain model because they're independent of the EF implementation (you could replace EF and retain the POCO's).
But if you're using EF with its EntityObjects, I believe you should convert to your domain model. If your Data Access was encapsulated in a WCF service which used a repository pattern internally, I wouldn't worry so much about returning EntityObjects from the Repository. But if you're using a Repository directly from MVC, use the Domain Model as the interface to the Repository.
We tend to always use a ViewModel as "the class in the middle" and map to and from the actual Model using...
Automapper
...or...
ValueInjecter
Your ViewModel can then be fairly independent of your Model in terms of structure if you want it to be.
What you describe is exactly what I've been doing for years, tying to follow n-tier application design.
Because you data will not always be organized the same way as your domain. What makes since in SQL is not always the same in your domain, as you've come across here.
Typically my domain knows what the repository looks like and has methods for converting to and from. My UI/views know what the domain looks like and have methods for retrieving that data (that goes in the controller).
So short answer, I would say, something in the middle (your business layer) and have that expose methods usable by your controllers to receive that data.
Related
My goal is async loading of related entities using DBContext.
Let imagine two projects. The first named MyApp.Domain and contains domain entities.
namespace MyApp.Domain
{
public class PlanPage
{
public Guid Id { get; set; }
}
}
namespace MyApp.Domain
{
public class PlanPageDay
{
public Guid Id { get; set; }
public Guid PlanPageId { get; set; }
}
}
The second project named MyApp.Infrastructure.EntityFramework and contains configuration of projection entities to database. It also contains class which extends domain entity and implements Entity framework specific logic.
namespace MyApp.Infrastructure.EntityFramework.Models
{
public class PlanPageEntity : PlanPage
{
private readonly ApplicationDbContext _applicationDbContext;
protected PlanPageEntity(ApplicationDbContext applicationDbContext)
{
_applicationDbContext = applicationDbContext;
}
public ICollection<PlanPageDay>? Days { get; set; }
public async Task<ICollection<PlanPageDay>> GetDays()
{
return Days ??= await _applicationDbContext.PlanPageDays
.Where(pd => pd.PlanPageId == Id)
.ToListAsync();
}
}
}
The purpose of this example is simple. We separate infrastructure code from domain code. Look how do we plan to use this concept:
// Entity initializing code. Placing somewhere in domain logic.
var plan = new PlanPage(/*some constructor arguments*/);
// Entity loading code. Placing somewhere in infrastructure implementation.
public async Task<PlanPage> GetPlanPage(Guid id)
{
return await _applicationDbContext.Set<PlanPageEntity>().FindAsync(id);
}
Note that we tell to Entity framework to use child class (PlanPageEntity) so it can handle all specific things that it can.
The question is: Is it possible to configure the EF so that it allows us to use this concept?
As requested here's a little more details for my opinion stated in the comments.
The main reason why I think your current approach is a bad idea is that it violates the separation of concerns design principle: when you are mixing domain models with data access models, you make your domain logic completely dependent on how you model the data in your database. This quickly limits your options because the database may have some restrictions on how you can model your data that doesn't fit well with the domain logic you want to implement as well as making maintenance difficult. E.g. if you decide to split up one DB table into two then you might have a big task ahead of you in order to make your domain logic work with those two new models/tables. Additionally, making performance optimizations in your database easily becomes a nightmare if not thought through ahead of time - and you shouldn't spend time thinking of optimizing your system before it's necessary.
I know this is a little abstract since I don't know much about your domain but I'm sure I could find more arguments against it.
Instead, separating data access models (and in general all external data models) from your domain models makes it much easier to maintain: if you need to make some changes to your database, you simply need to update the logic that maps the data from your data access models to your domain model - nothing in your domain logic needs to change.
In the examples you have given, you have already logically separated your domain models and data access models into two separate projects. So why not follow through with that thought and separate the two with a binding/mapping layer in-between?
Is it possible to configure the EF so that it allows us to use this concept?
Yes. Essentially you have DTO's, and your Entities derive from your DTOs. So when you fetch an Entity you can return it directly. But if you wouldn't be able to attach a non-Entity, so you'd have to map it. It's going to be inconvenient, and like 99.999% of bespoke entity and repository designs, will be ultimately a waste of time.
This is somewhat similar to the what EF already does for you. Start with persistence-ignorant Entity classes, and introduce persistence-aware runtime subtypes for scenarios that require them, which is basically just Lazy Loading.
I'm currently creating various entities in ASP.NET Core 2.2 with accompanying DTOs for a Web API. The client application would submit a DTO object to the relevant controller action. There using the AutoMapper, this would be mapped from the DTO object to an entity object. The resulting entity object would be saved to an entity framework repository which at this moment would be a Microsoft SQL database. For brevity let's assume that the time zones would be irrelevant in this case.
I was just wondering which approach would be more appropriate or to even have not have the calculation in either the DTO or Entity but perhaps within the Controller action.
Note: The actual code is more complicated and involves various calculations for various properties, I have simply chosen a simple case to illustrate my question.
Approach #1
// Entity
public class EventTimes
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public decimal TotalHours => (decimal)(End - Start).TotalHours;
}
// DTO
public class EventTimesDto
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
Approach #2
// Entity
public class EventTimes
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public decimal TotalHours { get; set; }
}
// DTO
public class EventTimesDto
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public decimal TotalHours => (decimal)(End - Start).TotalHours;
}
It depends on the actual context. Is the EventTimes an entity or is it rather part of your domain model?
Either way I would not put it in the dto as this is really just for transferring data, so it should not contain any logic (besides maybe validation).
Since the responsibility for this calculation is neither part of the dto, nor the entity model's, you could put the heavy calculation in an EventTimesCalculator something like this:
public class EventTimesCalculator
{
public decimal CalculateTotalHours(EventTimes eventTimes)
{
return (decimal)(eventTimes.End - eventTimes.Start).TotalHours;
}
}
If the EventTimes is part of your business layer / domain model, a more appropriate way would be to have a GetTotalHours() method inside of the model, instead of a property. Of course you would need to map it to the persistence model, if you want to save that information. Then again, since this information can be calculated, you don’t need to persist it at all, mainly because the logic might change (example: exclude breaks, interruptions or such).
My advice is to stop thinking in terms of database entities (which I assume you meant above).
At the end, it’s rather a detail where you put the calculation logic, more importantly is to have a straight forward design. Is the application monolithic put that logic in your layer that contains the business logic. Is it a distributed architecture, handle the calculation for the model in the service responsible for Eventing. Is it just a small API, keep it simple, put it where you or your team would expect it the most.
Iam using second approach because entity can contain raw which can be modified by application flow.
Common pattern Data transfer object (DTO) is exactly what you want for transport data between application layers which can transform data into desired output. Dto can't contain business logic but also can "prepare", "reduce" data which destination need.
For example:
If presentation layer need totalHours Iam doing this in model instead of entity.
Doing this in entity it would lead for endless modifications.
Another example can be user's full name Firstname, Lastname, AcademicDegree.
Entity can hold all of them but
one presentation need [academic degree] [firstname] [lastname] and
second need data in different format such as [lastname]
[firstname] [academic degree].
It is good keep property that make desired format in specific DTO instead of entity IMHO.
I in ASP.NET Core do this in onion architecture and view models and from my experience is easy to manage, change, prepare data for front-end or layers instead of change something in core.
If someone disagrees with me please let comment I like learn something new.
Hope it helps
I have read many articles about DDD and understood, that I should use my domain model classes in the Infrastructure level, so, I should use the same classes as Entity Framework infrastructure and use them to generate tables (code-first approach) etc. But my domain model can be fully different than Relational DB model.
Why I can't create one more model, infrastructure model, to create relational DB model and don't mix domain model with EF classes?
Consider this simple example:
Domain Model
public class Customer
{
public Customer(IRegistrar registrar)
{
this.registrar = registrar;
}
public int Age
{
get
{
// Just for this example. This will not work for all locals etc but beyond the point here.
var today = DateTime.Today;
return today.Year - this.DateOfBirth.Year;
}
}
public DateTime DateOfBirth { get; set; }
public int Register()
{
if (this.Age < 18)
{
throw new InvalidOperationException("You must be at least 18 years old");
}
int id = this.registrar.Register(this);
return id;
}
}
public interface IRegistrar
{
public int Register(Customer customer);
}
A lot of people when they do not have a domain model will do this in an MVC controller:
public ActionResult Search(Customer customer)
{
var today = DateTime.Today;
var age = today.Year - this.DateOfBirth.Year;
if (age < 18)
{
// Return an error page or the same page but with error etc.
}
// All is good
int id = this.registrar.Register(customer);
// The rest of code
}
There are a few issues with that:
What if the developer forgets to make the check for age before calling registrar? Many people will say, well that is a bad developer. Well whatever the case is, this type of code is prone to bugs.
The product is doing well so CFO decides to open up the API because there are many developers out there who are making great UI interfaces for customer registration and they want to use our API. So the developers go ahead and create a WCF service like this:
public int Register(Customer customer)
{
var today = DateTime.Today;
var age = today.Year - this.DateOfBirth.Year;
if (age < 18)
{
// Return a SOAP fault or some other error
}
int id = this.registrar.Register(customer);
// The rest of code
}
Now the developers can forget to make the check for age in 2 different places.
The code is also in 2 different places. If there is a bug, we need to remember to fix it in 2 different places.
If the company starts operating in places where the legal age is 21, we need to find all the places and add this rule.
If we are discussing the rules with BA, well we need to look through all the applications and find the rules.
In the above case we only have one rule: Age must be greater than 18. What if we had many more rules and many more classes? You can see where this will go.
EF Model
Your EF model may be like this:
public class Customer
{
public int Id { get; set; }
public DateTime DateOfBirth { get; set; }
// It may have a foreign key etc.
}
Application Layer Model
And your model for MVC view maybe like this:
public class Customer
{
// Or instead of Domain.Customer, it may be a CustomerDto which is used
// to transfer data from one layer or tier to another.
// But you get the point.
public Customer(Domain.Customer customer)
{
this.DateOfBirth = customer.DateOfBirth;
this.Age = customer.Age;
if (this.DateOfBirth.DayOfYear == DateTime.Today.DayOfYear)
{
this.Greeting = "Happy Birthday!!!";
}
}
public int Age { get; set; }
[Required(ErrorMessage = "Date of birth is required.")]
[Display(Name = "Data of birth")]
public DateTime DateOfBirth { get; set; }
public string Greeting { get; set; }
}
Here is a question: How many EF models have you seen with the Display attribute? I will let you decide if the EF model should concern itself with how it is displayed in the UI. Just the assumption that my EF model will be displayed in UI is wrong. Maybe the only consumers of my class is another web service. I don't think Display should be in the EF model but some may not agree with me; you make the call.
There are loads of questions on stackoverflow about people asking that sometime PropertyX is required and sometimes it is not, how can I do this? Well if you did not put Required attribute on your EF model and use your EF model in your view, then you would not have this issue. There will be one model for the view where PropertyX is a required field. That model will decorate PropertyX with the Required attribute, while another model for the view that does not require PropertyX will not decorate the property with the Required attribute.
ViewModels
And then you may have a viewmodel for a customer for a WPF application and you may have a javascript viewmodel for the frontend (KnockoutJS viewmodel).
Conclusion and answer to your question
So in conclusion, you can have different domain models than your entity models. Your domain model should be unaware of the database. If you decide to remove a column from one table due to normalization and put it into a table of its own, your entity model will be affected. Your domain model should not be affected.
I have read arguments on the net such as "this design takes too long, I just want to roll something out quickly and give it to the client and get paid". Well if you are not designing a product which will need to be maintained and features will be added to it but you are just designing a quick little site for your client then do not use this approach. No design applies to every situation. The point to take away is that your design should be chosen wisely with future in mind.
Also the conversion from entity model to domain to a model for MVC does not need to be done manually. There are libraries out there which will do this for you easily such as AutoMapper.
But I have to admit, there are tons of examples on the net and also in use in many applications where the entity models are used throughout the application and rules are implemented everywhere with loads of if statements.
Relation of this to DDD
When I read your question, I find something that catches the eye. It is this:
I have read many articles about DDD and understood, that I should use my domain model classes in the Infrastructure level, so, I should use the same classes as Entity Framework infrastructure and use them to generate tables (code-first approach)
To be honest, the best source of DDD knowledge it still the Blue Book. I know, I know, it is thick and hard to read. May be have a look at DDD Distilled by Vernon. The conclusion should be that DDD is not really about dealing with persistence but in deeper insight of the domain, better understanding your domain experts. Definitely, it says nothing about ORM.
Domain Model persistence
Domain models usually consist of objects (if we talk about object-oriented models) with state and behaviour. A model would have one or more entities and may be some value objects. In many cases you only have one entity per bounded context. Entities are grouped in Aggregates, that change together, forming transaction boundaries. This means that each change within the Aggregate is one transaction, no matter how many entities this change touches. Each Aggregate has one and only one entity, the Aggregate Root, which exposes public methods for others to work with the whole Aggregate.
So your Repository should take care of:
Persisting the whole Aggregate(no matter how many entities are there) within one transaction, for new and updated objects
Fetching the whole Aggregate from your persistence store, by its identity (Aggregate Root Id property)
You for sure will need some Queries but they can query how they want as soon as they do not amend the domain model state. Many add querying methods to the Repository but it is up to you. I would implement them as a separate static class with DbContext extension methods.
Models not matching each other
You mentioned that your persistence model does not match the domain model. This might be the case although for many situations it is not the case. There are a few ways of dealing with this:
Keep state separate of the behaviour and have it as a property in the domain object. Like Order with AddLine and so on, and OrderState with all these Total, CustomerId and stuff like this. Bear in mind that this might not work nice for complex aggregates.
Concentrate on the two main methods of the Repository that I mentioned above - Add and Get. Each Repository works for one type of Aggregate only and how you map between them is up to you.
Combined with the point above, you can reconsider using ORM and do something else. Basically you can just use ADO.NET but the easiest is to use some sort of document-oriented stuff like NoSQL although many would disagree. Check also this article about PostgreSQL JSONB storage as persistence.
Remember that the main point is to have the Repository that will do the work for you and potentially (probably this would never happen but still) use another store.
You might also be interested in another Vernon's article where he discusses using EF specifically.
I am using the Repository pattern with.NETCORE and am trying to return data back from an HttpGet request. The data I want back is from multiple un-related tables in SQL. I am trying to wrap my head around being able to retrieve the data from each respective repository and return an object with all data. I hope this makes sense, I am stuck and started to go down "Unit of Work" but can't find a good example that does what I would like, query multiples in un-related tables from one get request. Thanks in advance.
Step 1. Create model classes (domain model layer) for each table / view or the dataset that comes from the SQL database. Shown below:
public class DataFromTable1
{
// properties mapped with the sql table columns
}
public class DataFromTable2
{
// properties mapped with the sql table columns
}
public class DataFromTable3
{
// properties mapped with the sql table columns
}
Step 2. Write data access classes that will call the SQL database (stored proc or direct SQLstatement – I don’t recommend direct table access from .net though) to populate your model classes created in step 1. You can use any repository pattern in this step.
Step 3. Create a view model class that will wrap the model classes with its properties and hydrate them by calling the data access class create in step 2. Generally view model classes are created under the MVC project.
public class MyViewModelClass
{
public DataFromTable1 DataFromTable1 { get; set; }
public DataFromTable2 DataFromTable2 { get; set; }
public DataFromTable3 DataFromTable3 { get; set; }
}
Step 4. Use this view model to display the data in the view.
Hope this helps.
I'm working on making a image site and I'm wondering how I should structure the Create/Update methods in my Linq to Sql repository?
I have a Photo entity that is structured like:
public class Image
{
public int ID { get; set; }
public int OwnerId { get; set; }
public string Url { get; set; }
public IEnumerable<Tag> Tags { get; set; }
}
I have the following tables: Images, Tags, ImageTag
Now, I'm wondering when I call my CreateImage method in my ImageRepository, should I also be creating the Tags in the Tags table and the making the mappings in the ImageTag table?
Likewise, when I call UpdateImage, should I be checking if the tags have changed, and if they have then deleting entries in the ImageTag table and adding in different ones (as well as possibly adding new Tags to the tags table)?
Or should both of these use cases happen in a separate repository call?
Basically, how is this parent/child, one-to-many relationship handled typically in a typical linq to sql repository?
I would say it is not the responsibility of the repository to understand the relationships between the entities in your model. After all, if you were to change the way you persist your data (to a no-sql solution for example, or even if you just change your db schema), your entities and your model shouldn't change.
So your best bet is to have separate repository calls, and wrap the calls inside a unit of work. (A Unit of Work is basically an abstracted out transaction).
Your unit of work and the various calls to the repository would be a layer of abstraction above the repository. I don't know the rest of your model, so that could be different things. It could be a method on the Image object. You could have a Mediator. Or, if you are approaching this from a DDD perspective, a Domain Service.
Cheers.