Handling Changes Inside Aggregate with Separate Domain and Persistance Layer - c#

I'm fairly new to DDD but I am trying to cram as much as possible as fast as possible. I followed https://github.com/dotnet-architecture/eShopOnContainers as a guide for how to structure my code with Mediatr and EF Core.
Fortunately for this application, the persistence and domain model are the same. Unfortunately for me, my data layer does not match our domain model as it is a legacy db.
So i am separating the domain from persistence which is well and good. But I am having a hard time understanding where if i do this code block in a command handler(trying to make it simple and clear)...
var aggregate = repo.GetById(1234);
aggregate.AddItemToList(item);
repo.SaveChanges();
How can i cause the underlying database context of the repo to be aware of the changes that were applied. Only thing i can think is to have a repo.Update(aggregate) call, that would then try to apply db calls to update various places of the db.
This seems like a smell to me.
Any insights would be great.
Thank you!
Edit:
Should the repository pattern with a separate Domain and Persistence layer return the presistance layer's model or the domain's?
For example:
I have a aggregate Company. And i have a database table called CompanyLegacy which is modeled in the persistence layer using entity framework core.
Should my repository be CompanyLegacyRepository or CompanyRepository? If CompanyRepository, that would mean i query the CompanyLegacy table, and map it to a Company domain model then return it. This model, would not be change tracked. This is where my issue comes from.
But if I'm supposed to do a CompanyLegacyRepository then it seems like that doesn't adhere to DDD guidelines where all actions to be applied to the aggregateroot.

Should the repository pattern with a separate Domain and Persistence
layer return the persistence layer's model or the domain's?
Repository should return your Domain model. If you are using DTOs (such as CompanyLegacy) in your Infrastructure layer, it is the responsibility of your Repository to map them to your Domain models. Please note that in a Layered Architecture, the Application layer is not supposed to know about the DTOs used in the Infrastructure layer... it's your Domain models which are the heart of your application. See this question which is closely related to yours.
Your Repository should be called CompanyRepository. You can define an interface for this repository like:
public interface ICompanyRepository
{
// Company is your domain model not DTO (i.e. your legacy model)
Company GetById(int id);
void Add(Company);
void Update(Company);
}
Change Tracking
Entity Framework change tracking has it's limitations, this question is an example of one of those Disconnected Scenarios, where we cannot rely on EF Change Tracking (because of DTOs). The implementation of the above repository would be like:
public CompanyRepository: ICompanyRepository
{
Private MyDbContext _context;
public CompanyRepository(MyDbContext myDbContext) { _context = myDbContext; }
public Company GetById(int id)
{
var companyLegacy = _context
.CompanyLegacy
.AsNoTracking()
.Where(c => c.id = id)
.FirstOrDefault();
return MyMapper.ToCompany(companyLegacy);
}
public void Add(Company company)
{
var companyLegacy = MyMapper.ToLegacy(company);
_context.Add(companyLegacy);
_context.SaveChanges();
}
public void Update(Company)
{
var companyLegacy = MyMapper.ToLegacy(company);
_context.Update(companyLegacy);
_context.SaveChanges();
}
}
This tutorial is helpful for more advanced operations and you can find more info about EF Core change tracking here.
this answer is related to EF 4/5/6 (not core) but gives you some idea about using unique identifier to decide if an entity should be Added or Updated.

Related

DDD and Entity Framework

I'm looking to use DDD in an application with EF as the data access layer. Most of what I've read has suggested separating the domain model classes with the data classes, which makes sense to me and keeps the domain cleaner. I'm running into an issue with going from domain layer to persistence layer.
Say in my domain I have the following 3 classes:
class Root
{
int RootId { get; }
IReadOnlyCollection<Child> Children { get; }
Child AddNewChild(IReadOnlyCollection<Data> data) {
// Validate, create, and add child to internal list
// Then what?
}
// More irrelevant properties/methods
}
class Child
{
// This has a LOT of entries
IReadOnlyCollection<Data> Data { get; }
// More irrelevant properties/methods
}
class Data
{
decimal Value { get; }
// More irrelevant properties/methods
}
The EF data classes would be very similar, but implemented in a way EF is happy with.
Root in this case is my aggregate root, with the others being entities\value objects contained in the aggregate, so I would have an IRootRepository in order to query, add, and remove Root entities implemented with EF.
One issue is how does the Root.AddNewChild() method persist the data with this? My understanding is that the user code would get a unit of work (implemented via DbContext), use that to access the IRootRepository to load a Root, and then call Root.AddNewChild(), but without Root being an EF object there isn't a way to track that on the persistence level. I've considered making Root an abstract class and adding the persistence stuff in there by inheriting from Root with my EF data class, but this seems wrong. I've also considered domain events, but is that too flimsy or is communicating with persistence layer what they are for?
The other issue has to do with the Child.Data property which will have a lot of entries. I don't want to pull every Data object from the database when loading my aggregate root for performance reasons, but I don't see a way of returning that data after loading the Root without somehow going through the persistence layer. I could create an IDataRepository for that, but then Child would have a dependency on it which seems odd and also it violates the DDD "one repository per aggregate" guidelines.
It seems like beyond very basic scenarios this format falls apart. Am I missing something on how to structure all of this? Should those problem methods fall to the repository or some other service?
Thank you for your help!
The Root.AddNewChild() method does not call anything to store the state in the database. Storing the state is an infrastructure matter and the domain layer should be persistence ignorant. Storing the state is actually a feature of the repository, and the repository is the one to know about the unit of work:
public class AddChildToRootService
{
private readonly IRootRepository rootRepository;
public async Task AddChildToRootAsync(IReadOnlyCollection<Data> values, int rootId)
{
var root = await rootRepository.GetByIdAsync(rootId);
root.AddNewChild(values);
await rootRepository.UpdateAsync(root);
}
}
public class RootRepository : IRootRepository
{
private readonly IMapper mapper;
private readonly DbContext context;
public async Task<Domain.Root> GetByIdAsync(int id)
{
return await context.Roots
.Where(root => root.Id == id)
.ProjectTo<Domain.Root>(mapper.ConfigurationProvider)
.FirstOrDefaultAsync();
}
public async Task UpdateAsync(Root root)
{
var entity = await context.Roots
.Where(entity => entity.Id == root.RootId)
.FirstOrDefaultAsync();
// reverse mapping here
await context.SaveChangesAsync();
}
}
Regarding Child.Data, you are allowed to make multiple domain model that overlap, with different level of details. This is called a polysemic domain model. In that situation, you can have a RootRepository, that manipulates
Root and Child aggregate, and a RootDataRepository, that manipulates RootData, ChildData, and Data aggregate. All models and repository map to the same persistence tables but are considered two different root aggregates at the domain layer, each with their own domain model and repository. Then you may use the RootDataRepository in use cases that need the Data level of details, and the RootRepository in use cases that do not need them.

Repository Pattern EF Core Update method

I have a question about using the Repository Pattern and Unit of Work pattern in a MVC Web Application with Entity Framework Core.
I am currently implementing the update functionality in the controller. Now, at this point I am not sure what the best way is to update the entity. I have watched some videos where they said that an Update method should not be present in a repository like this:
public T Update(T entity)
{
DbSet.Attach(entity);
var entry = Context.Entry(entity);
entry.State = System.Data.EntityState.Modified;
}
So that means that I will have to do it like this in the controller:
public IActionResult Edit(int id, [Bind("NeighbourhoodGroup,Neighbourhood,NeighbourhoodId")] Neighbourhoods neighbourhoods)
{
var neighbourhoodsFound = unitOfWork.Neighbourhoods.Get(id);
neighbourhoodsFound.Neighbourhood = neighbourhoods.Neighbourhood;
neighbourhoodsFound.NeighbourhoodGroup = neighbourhoods.NeighbourhoodGroup;
}
However, that means that I will have to do this in all controllers, even if the object has alot of Properties?
I hope someone can give me some advice on what the best approach would be.
In your repository you can have the update functionality as simple as this:
public void Update(T entity)
{
DbSet.Attach(entity);
ApplicationContext.Entry(entity).State = EntityState.Modified;
}
While in the controller or from wherever you prefer to do your update you can get the entity preferably by id, modify all the properties that you want to modify on entity, call the the Update method from the repository which is going to set its state to modified and finally call the Save or SaveAsync method on the EF context. Your EF context should be exposed in your UnitOfWork.
For more detailed explanation you can see this post, it will be very helpful. EF Repository Pattern
I don't see the problem in having Update method in repository. It's OK. It's more complex to read data from repository based on criteria. here you can check an example from Microsoft.
Controller isn't a good place to describe your business cases: do some business logic then save to repository etc. Consider MediatR as a way to describe particular business case instead of putting it into controller.
Also it's useful to read about clean architecture.

Linq to Sql and separation of concerns - am I doing this right?

I have a project that I'm working on that I'm using LINQ to SQL for and I have set up business objects/models to use in my web app. I am looking for some feedback on how I've set all this up to see if it makes sense and if there's anything I should be doing differently.
Here's an example model:
public class User
{
private MyDataContext _db = new MyDataContext();
private MyLINQUserClass _user = new MyLINQUserClass();
public string Name
{
get
{
return _user.Name;
}
set
{
_user.Name = value;
}
}
public User(int UserID)
{
_user = _db.Where(u => u.UserID == UserID).FirstOrDefault();
if (_user == null)
{
_user = new MyLINQUserClass();
}
}
internal User(MyLINQUserClass user, MyDataContext db)
{
_db = db;
_user = user;
}
public void Save()
{
_db.SubmitChanges();
}
public static User Add(string Name)
{
MyDataContext _db = new MyDataContext();
MyLINQUserClass _user = new MyLINQUserClass();
_user.Name = Name;
_db.MyLINQUserTable.InsertOnSubmit(_user);
_db.SubmitChanges();
return new User(_user, _db);
}
public static IList<User> Get()
{
MyDataContext _db = new MyDataContext();
return _db.MyLINQUserTable.Select(u => new User(u, _db)).ToList();
}
}
For clarity, I am using this type of model already quite heavily in the project (the above is just an example I threw together for the post on the fly) and it works very well. My question is more of a "learning" question ... I know it works. I'm just not sure if there is something I should be doing differently that is better and if so, why.
Thoughts?
I suppose there are no right answers to this kind of questions. It is a matter of design, preference and requirements. I will try to show my view...
I always liked the Repository pattern to keep the concerns seperated. I would use a repository of type T to retrieve the T entities (talking generics). These would be the entities participating on my business model. In your case, I would have a UsersRepository class, returning User entities. This Data access layer (DAL) would handle my data access concern.
My business model would use the entities to do its business. In simple CRUD applications, maybe no other objects other the entities returned by my repositories would be needed. In more complicated applications, new classes would be needed, using the repositories of the DAL to retrieve data as entities. This business layer would handle my main business functionality concern (calculations etc).
Then, for display purposes, you could need perhaps another structure. For instance, if you follow the MVC pattern (you could also see the Microsoft article) you would need to create another model to fit your display purposes. This GUI layer following the MVC pattern would handle my graphical display concern.
Hope I helped!
This is the so-called Data Access Objects pattern. The User is a DAO to MyLINQUserClass which might be called the domain class.
The DAO pattern is designed for single responsibility: only the DAO "knows" the data layer while the domain class can concentrate on business logic. The domain class is persistence ignorant. So far, so good.
However, there are (at least) three great drawbacks of this pattern:
It tends to create lots of boilerplate code
It is hard to compose object graphs, because a DAO represents only one row in the database and fetching object graphs easily degenerates into one query per object or collection of child objects.
It is hard to work transactionally, because a DAO can't manage a transaction spanning an entire object graph. So you need some overarching layer to handle transactions.
Most ORMs however, have a different persistence-ignorance model than DAO. They have repositories and units of work. In L2S the Table is a basic repository and the context a unit of work. The "domain" classes, like MyLINQUserClass, can be considered persistence-ignorant. (Admitted, they are stuffed with boilerplate code that serves persistence and change tracking, but it is generated and it can practically be ignored). So all responsibilities for CRUD operations have been assigned, and there's no need for other objects carrying these responsibilities.
The way you implement it makes it extra hard to work with object graphs and transactions because each DAO has its own context, so you can't compose LINQ queries involving multiple DAO's in a way that the LINQ is translated into one SQL statement. And doing multiple save operations in one transaction is a challenge.
Conclusion
By using DAO in a linq-to-sql environment you're mixing CRUD responsibilities. You get all the disadvantages of the DAO pattern and can't exploit the power of the repository/UoW pattern to the full. I would strongly recommend to make a choice for one or the other, and I would choose L2S (well, actually I would choose Entity Framework).

Mvc4: N tier architecture

Tools: Mvc4, Sql server, Nhibernate
I am learning Ntier architecture and plan to learn this with a small example. This will be a student registration application which will have a form for
a. first name
b. last name
c. address
d. Student Id
The application will be able to
a. Get student by Id
b. Get all students
c. Register new students/Save student
d. Edit a student
e. Delete a student
I plan to have the following tiers
Presentation layer (seperate project mvc 4 application)
--- html for student form goes here. I can use jquery etc here
--- my controller will call the service
Service layer (seperate project : class library project. In this case only the web will be my client. I will learn to use webAPI or wcf for this later in another project)
--- StudentService here
--- IstudentService here
Business layer : (seperate project : class library project)
??
Data layer : (seperate project : class library project)
??
Database : (sql server database)
Now I got confused and my questions are:
where will I create my student model (which layer ?)
What will I be writing in my business layer for this student example I have.
What will go in my data layer? Which methods will I be writing? Are they methods that will communicate
with the database directly?
Some examples will be great. I will look for a good IOC container.
Here is sample code below:
public interface IStudentService
{
IEnumerable<Student> GetStudents();
Student GetStudentById(int id);
void CreateStudent(Student student);
void UpdateStudent(Student student);
void DeleteStudent(int id);
void SaveStudent();
}
public class StudentService : IStudentService
{
private DataContext _datacontext;
public StudentService()
{
_datacontext = new DataContext();
}
public IEnumerable<Student> GetStudents()
{
var students = _datacontext.Students;
return students;
}
public Student GetStudentById(int id)
{
return _datacontext.Students.Find(id);
}
public void CreateStudent(Student student)
{
_datacontext.Students.Add(student);
_datacontext.SaveChanges();
}
public void UpdateStudent(Student student)
{
_datacontext.Entry(student).State = EntityState.Modified;
//_datacontext.Entry(student).State = EntityState.Modified;
_datacontext.SaveChanges();
}
public void DeleteStudent(int id)
{
var student = _datacontext.Students.Find(id);
_datacontext.Entry(student).State = EntityState.Deleted;
_datacontext.SaveChanges();
}
public void SaveStudent()
{
_datacontext.SaveChanges();
}
}
You create your model in your data layer. You will also create models in your presentation tier (for your view models). You would usually do some kind of mapping between your data model and your presentation model in your controller.
Simple apps often don't really need a business layer. Particularly if your app just saves data from forms into tables. However, in an app such as this you might do things like "You can't register for this class unless you've already completed that class" or you might have "You have already registered for more classes than you are allowed" or what not. These are business rules that must be enforced somewhere, and that is usually in the business layer.
Your data layer will probably just be your Entity Framework model. It's just your code to load and save your model to the database.
There are many IoC containers.. I like Ninject, but other people like other ones.. It's generally a matter of personal preference.
The above is how you would do it in a simple application. In more complex applications, you might have a model in your business layer as well. It all depends on the complexity of your application, and whether you need to represent your data at a business level differently than you would at a data model level.
For instance, you might have a list of business objects in the business layer, but these objects are represented differently in your data layer for performance reasons. But all of this is really not things you should worry about at this point. Just understand that as your applications become more complex, you may have the need to do things differently.
You need to have a look on Onion Architecture. It is a bit out of date in terms of MVC versions, but the tiers are layered greatly.
In terms of IoC container I'd recommend looking on Autofac - easy to use with a lot of features, like registration by conventions and multi-tenant.
As for your questions:
What I usually have is on form submit, controller would get a StudentViewModel submitted, then I would convert it to a Student object and hand over to IStudentRepository that is injected into the controller. And IStudentRepositry will save it to the DBContext. The repository interface would sit in Domain layer, but implementation of the repository would be in Data layer. And DI container will match one to the other.
The trick here is to have all interfaces in Domain layer and implementations sitting wherever they should be. And Domain layer should not be dependent on any other layer (read Domain project would not have reference to Data and Web projects). But Web would depend on Data and Domain layers. You only need Data layer dependency in Web layer to configure IoC container, as web layer is your aggregate root, and IoC should be configured there. But you should never use Data objects directly in any of the operations, you should be injecting interfaces for repositories or services.
There is a lot have been said about the layered architecture, so start with Onion Architecture first, then you'll have a better idea of what you need.

Entity Framework in Layered Architectures

Recently I've read article "The Entity Framework In Layered Architecture" and there is written we can send EF-entities to client through WCF. But in many threads on Stackoverflow people tell that POCO(DTO)-objects should be used when we use WCF.
And I have some questions.
Why did Microsoft add DataContract attribute to EF-entities? Does Microsoft wanted us to use these objects everywhere in our applications? Or this is only for very simple applications and for rapid development?
If I use POCO-objects, should I create auto generated EF-Entities, POCO-Entities and after that use any mapping library between them? Or I should use only POCO-objects in all components of my application?
If I already have my own business entity, which has some methods, and it should be mapped to POCO object, on which layer should I convert POCO-object to my entity (for example, I have persistence layer, business logic layer, service layer(WCF), presenter layer (client, use WCF), UI layer)? Or I shouldn't make such my own entities?
Thanks in advance
1.Why did Microsoft add DataContract
attribute to EF-entities? Does
Microsoft wanted us to use these
objects everywhere in our
applications? Or this is only for very
simple applications and for rapid
development?
Generally speaking, it is a bad idea to expose your EF-Entities in the service layer because that hardly couples your service layer and model representation. so any changes done in the model ends affecting directly your services, not a good idea. also you will have to version your service layer in some moment, so avoid to expose the EF entities in your service layer.
2.If I use POCO-objects, should I create auto generated EF-Entities,
POCO-Entities and after that use any
mapping library between them? Or I
should use only POCO-objects in all
components of my application?
You can use POCO objects inside your service layer, to decouple it from any underlying layers (see Automapper, to cover the Entity-DTO mapping cost). but you could still use the autogenerated EF-entities among the data and business layers in your architecture. just try to not rely in EF specific features of your generated domain model in other layers different from data layer. to ease the migration to another ORM frameworks.
If I already have my own business
entity, which has some methods, and it
should be mapped to POCO object, on
which layer should I convert
POCO-object to my entity (for example,
I have persistence layer, business
logic layer, service layer(WCF),
presenter layer (client, use WCF), UI
layer)? Or I shouldn't make such my
own entities?
Service layer http://msdn.microsoft.com/en-us/library/ms978717.aspx. you would be using your domain model transparently among the server tier (persistence, business, service and presenter layers) of your application, and the only layer that will require you a DTO mapping is the service layer, see question 1. (additionally if you are using ViewModels inside your the presenter layer -nice idea- you will require to use POCOs-mapping in the presenter layer too).
You can have POCO entities handwritten and completely separated from the persistence layer. SDReys is right, using generated EF entities as your model is smelly.
Here is the rough layout for a simple POCO model and the context to support it.
public class MyApplicationContext : ObjectContext, IMyApplicationContext {
public MyApplicationContext() : base("name=myApplicationEntities", "myApplicationEntities")
{
base.ContextOptions.LazyLoadingEnabled = true;
m_Customers = CreateObjectSet<Customer>();
m_Accounts = CreateObjectSet<Account>();
}
private ObjectSet<Customer> m_Customers;
public IQueryable<Customer> Customers {
get { return m_Customers; }
}
private ObjectSet<Account> m_Accounts;
public IQueryable<Account> Accounts {
get { return m_Accounts; }
}
public Account CreateAccount(Customer customer) {
var account m_Accounts.CreateObject();
account.Customer = customer;
return account;
}
public Customer CreateCustomer() {
return m_Customers.CreateCustomer();
}
public void AddAccount(Account account) {
m_Accounts.AddObject(account);
}
public void AddCustomer(Customer customer) {
m_Customers.AddCustomer(customer);
}
}
public class Account {
public int Balance {get;set;}
virtual public Customer{get;set;}
}
public class Customer {
public string Name {get;set;}
virtual public List<Account> Accounts{get;set;}
}

Categories

Resources