Is it good practice to create a database from a domain model, using a code-first approach, which then dictates what the database schema looks like (using entity framework). Or should you always design the db first and then create you domain model(s)?
From 2009 to 2013-ish, that's exactly what I have done (and answered many SO questions doing exactly that!) - using Entity Framework as our "Aggregate Roots" and extended them from there with value objects (poco classes) and so on.
I am here today to tell you this: DON'T DO IT!
The latest "rutt-rough" coming from DDD in C# is how most of us have done this - a direct "Table to Entity/Aggregate" mapping. All this does is give a false sense of separation without any bounded contexts.
In the past, I usually created a folder called, say, "Users". I also had an entity called User.cs for code first (or in the designer, a table called User). I was allowed to add my own methods and properties onto a User.cs partial. I would also group all value objects related to users within a subfolder. So, it looked like this:
\Users\
^- User.cs partial with additional so called "logic"
- UserService acting with "business logic" on User and related properties.
\users\EmailTemplates\
^- I often needed a way in DDD to store other "Entities" related to this AR.
\Users\ValueObjects\
^- UserAddress.cs
- UserTarget.cs
- UserTypeEnum.cs
- // basically a dumping ground
Now, after a year, we've come to realize that we have so much work on UserTarget that it is huge. It is becoming a huge service-like class with 1000 lines of code. In DDD, this really should be it's own bounded context, called UserTargets and act as its own aggregate root, with many value objects in it. But yet, there isn't anything stored in the DB. Do we create a entity in code first? have an exception in attributes to ignore it? etc.
It just feels so dirty and hacky any way you cut it.
Let's take another example out of the DDD playbook:
Biz: "I have a user that needs to signup. Once they signup, they will have a project."
Dev team: "Great, we have the following entities: User and Project"
public class User {
public List<Projects> Projects { get; set; }
public Team Team { get; set; }
}
public class Team {
public List<Projects> Projects { get; set; }
}
public class Project {
public User Administrator { get; set; }
public List<User> Members { get; set; }
}
That alone is a problem. Now that we are using CQRS/event sourcing often, it's easier to model it more like:
User : AggreateRoot
Team : AggregateRoot
Project : AggregateRoot
UserProject : AggregateRoot
UserSignup : AggregateRoot
TeamProject : AggregateRoot
...etc
Note the additional aggregates? How would you represent them in the DB? FKs right? Well, what if there are additional properties like a TeamProject.ContestEntrySubmitted datetime? Ah yes, now those FK child tables get ugly in EF and code first.
The domain is for your pure business design - to solve solutions. Not for how many POCOs you can organize to make EF happy in code gen. Not as your CRUD layer to bypass all business logic, new up an ObjectContext, and call Save(new User()). I see developers wasting so much time with this or that EF issue, wrestling with "do we side-step DDD to make EF do this? or do we spent a few days changing EF's internals and T4s to do that instead? we'll remain DDD-ish, but many that's a lot of work."
So I am hear to ask, "Why do it at all?" Separate the domain from any storage model.
In CQRS, your "Domain" is write-only anyways. Having them as a EF objects already throws event sourcing out the window, and now forces you to handle states.
By freely writing domain aggregates and entities allows us to bind multiple projects, or users, to each other without affecting the other aggregates. if the other aggregates, say User, wants to have a project count, sure, listen for the ProjectCreated event for that userid who created it and ProjectCount++ and call in the day.
The point is, once you apply DDD to Event Sourcing patterns, you look at your domain quite differently. It is no longer a "stateful" domain in a sense that you can query anytime to get the last 10 years who signed up, or knowing you can just go to the DB and run that SQL. No, instead it is more like, "I need to make a state change to X entity. It will be caused by this, this and that when in these specific states. Now, when the planets have aligned, we'll change the Username to be this in a new ChangedUSernameBecausePlanetsAligned event."
I guess my point I am trying to make is going down the EF Entities-as-DDD AggregateRoots feels so dry in the end, and without any DDD substance. You end up with nearly 30 or 50 "aggreateroot" folders in your monolithic MyProject.Domain assembly. And is what Udi basically calls, a Big Ball of Mud.
My general rule now is not to use any frameworks for my domain - freeing me up to structure it in pure DDD as I see fit, and it has been really enjoyable. There are no confining frameworks or restrictions. I've actually re-written entire domains in F#, just for fun and since there was no need for any "queries", it just happened.
Then, wjem moving into the Event Sourcing world, you start to realize exactly why your domain is "write only" and think about how you can "push" data to the views, instead of giving the views something to query from your domain. Removing that Querying part from your domain really makes this nice and neat.
--
Eh, I think I just realized that I wrote an answer that basically says, "Hey, don't do Entity Framework and DDD. Check out CQRS and DDD instead." LOL
Related
I'm learning ASP.NET MVC and I'm having some questions that the tutorials I've read until now haven't explored in a way that covers me. I've tried searching, but I didn't see any questions asking this. Still, please forgive me if I have missed an existing ones.
If I have a single ASP.NET MVC application that has a number of models (some of which related and some unrelated with each other), how many DbContext subclasses should I create, if I want to use one connection string and one database globally for my application?
One context for every model?
One context for every group of related models?
One context for all the models?
If the answer is one of the first two, then is there anything I should have in mind to make sure that only one database is created for the whole application? I ask because, when debugging locally in Visual Studio, it looks to me like it's creating as many databases as there are contexts. That's why I find myself using the third option, but I'd like to know if it's a correct practice or if I'm making some kind of mistake that will come back and bite me later.
#jrummell is only partially correct. Entity Framework will create one database per DbContext type, if you leave it to its own devices. Using the concept of "bounded contexts" that #NeilThompson mentioned from Julie Lerhman, all you're doing is essentially telling each context to actually use the same database. Julie's method uses a generic pattern so that each DbContext that implements it ends up on the same database, but you could do it manually for each one, which would look like:
public class MyContext : DbContext
{
public MyContext()
: base("name=DatabaseConnectionStringNameHere")
{
Database.SetInitializer(null);
}
}
In other words, Julie's method just sets up a base class that each of your contexts can inherit from that handles this piece automatically.
This does two things: 1) it tells your context to use a specific database (i.e., the same as every other context) and 2) it tells your context to disable database initialization. This last part is important because these contexts are now essentially treated as database-first. In other words, you now have no context that can actually cause a database to be created, or to signal that a migration needs to occur. As a result, you actually need another "master" context that will have every single entity in your application in it. You don't have to use this context for anything other than creating migrations and updating your database, though. For your code, you can use your more specialized contexts.
The other thing to keep in mind with specialized contexts is that each instantiation of each context represents a unique state even if they share entities. For example, a Cat entity from one context is not the same thing as a Cat entity from a second context, even if they share the same primary key. You will get an error if you retrieved the Cat from the first context, updated it, and then tried save it via the second context. That example is a bit contrived since you're not likely to have the same entity explicitly in two different contexts, but when you get into foreign key relationships and such it's far more common to run into this problem. Even if you don't explicitly declare a DbSet for a related entity, it an entity in the context depends on it, EF will implicitly create a DbSet for it. All this is to say that if you use specialized contexts, you need to ensure that they are truly specialized and that there is zero crossover at any level of related items.
I use what Julie Lerman calls the Bounded Context
The SystemUsers code might have nothing to do with Products - so I might have a System DbContext and a Shop DbContext (for example).
Life is easier with a single context in a small app, but for larger application it helps to break the contexts up.
Typically, you should have one DbContext per database. But if you have separate, unrelated groups of models, it would make sense to have separate DbContext implementations.
it looks to me like it's creating as many databases as there are
contexts.
That's correct, Entity Framework will create one database per DbContext type.
So to put things into perspective:
Until now i've had some experience with working with Entity Framework edmx models. The process (layer wise) would summarize to:
creating the database, having a layer of objects generated in the edmx file
having a layer of business objects (i am not sure if business is the right word) that are initialized from the edmx objects (and only the business objects are used inside my application)
in the MVC site having a layer of view model objects wherever needed (whenever generating views directly from my business objects would not work)
I am under the impression that with Code First the database layer objects (previously named edmx objects) and the business layer objects are one and the same, practically skipping a layer. That is what a colleague who had much more experience than me told me.
The problem is that i don't think this is quite applicable. Limitations of code first like scalar keys, having navigational properties inside objects, being unable to map private fields inside the DB without workarounds and being forced somewhat to have autoproperties everywhere feel that i am messing up my business objects.
Quick Example:
I have the entities of:
Team : TeamId and Description (Backend, FrontEnd etc)
Group : GroupId and Description (Developers, TeamLeaders, PMs, etc)
Status: an object that has a Team and a Group, something that is not to be kept inside the DB
User: UserId, FirstName, LastName
Employee: a user which also is part of a Team and a Group (inside it has a User property and a Status property)
The Users table will be denormalized in the sense that it will be containing all the info my User class has, but also have a TeamId and a GroupId, which will be populated only if the User is also an Employee. So basically Employee and User are mapping to the same table
This leads to some weird workarounds, since for instance in the Employee class i need to expose UserId as a primary key, and not get it through the User property's UserId (because the key needs to be scalar) which is ugly; also, even though i have a Status property inside the Employee class, i still need to have 2 additional properties (TeamId and GroupId, gotten from the Status properties Team and Group) in order to have scalar foreign keys to Groups and Teams, which again is cumbersome and feels messy. Adding inside the Group/Team class a virtual IList for navigational purposes also seems unneeded (though from what i've seen this can be skipped). Also having only auto properties for the objects seems wrong, i want to have privates instantiated by the ctor and only getters for them.
Am I not getting it ? Do i still need the additional layer even while using code first ? Is my model messed up from the beginning ? Sorry i cannot provide you with the code, but i am not home at the moment, and the code block seems very dodgy to use :D
I tend to work within the repository and service pattern(s). In my expereince, I have always found it easier to solidify what my application is going to be using (models) and how they will stored (structure). I lean on the side of building up the database with all the linking and FKs, building an EF model (EDMX), and then adding a layer on top of that as a Service/Repo layer. This way, your application always just references that Service/Repo layer, and if your EDMX breaks or you have to change the way something is calling your EDMX, you only have to fix it in one spot. Recently I have been doing a mix of the IRepository pattern mixed in with a Service class, and it seems to be meshing really well and is easy to use. Hope this clarified some for you, best of luck!
I've started to develop ASP.NET MVC application using Entity Framework and I wish to use DDD. It's my first time using DDD in ASP.NET (used until now in PHP), so I'm little confused.
I'm using code-first approach, so I'm creating my entites in the core and then the DbContext in the Infrastructure.
My questions is about data annotations: Is it OK to annonate the entities in the core? with Required, DataType, etc. or I have to create entries with pure C# validation (in the setters and getters) and then create a map objects for the database creation?
For example, I got:
public class Account
{
public string AccountName { get; set; }
}
Can I annonate the AccountName with [Required] or I need to create a map class which will just reflect the exact same properties in the Account class but will have attributes and that will be the class that I'll use in Entity Framework DbContext?
Thanks!
Neither.
Your entities should have barely any public getters or setters. Domain model is a behavioral model, not a data model. Your entities should have private fields and methods that changes the entity state. Those methods should have a business meaning and should protect entities invariants (validate input). For example - we have UserAddress and want to change it. Is it just user.Address = newAddress? NO. What's the meaning of changing that? Maybe your User want to FixMistypedAddress(str). Or maybe your UserMoved(newLocation)? Different business rules may apply tho those scenarios. For example when UserMoved() we want to send him a champagne bottle, but not when he just fixed a typo. You should already see that there is no use of data annotations here because we don't just set properties but we do meaningful operations.
Entities should always be valid. That mean there should be no way to put it in an invalid state. Data annotations only allow you to check whether the object is valid or not. They not guarantee is will be valid all the time.
IMO Data annotations are fine for:
Using Entity Framework in a CRUD application (no DDD applied)
In DTO or ViewModels. In other words - for validating user forms, not entities.
So the first quiestion for you is: Are you doing CRUD or DDD?
I'd say either way is fine.
If you want a more pure approach you would create a buddy class that has the metadata on it however it is also acceptable to put it directly on the domain class.
In the end it comes down to how much you want to remain "pure" and how much extra work you want to put into maintaining buddy classes, not to say that it is a bad thing.
I´ve not had much contact with Entity Framework yet and therefore I´d like to hear some guys with experience.
I´ve got an MVC project and my DataAccess lies in a different project where I want to place my EDMX file.
So how would I like to name this file? Per default it is "Model1.edmx" but in the context of MVC I don´t feel comfortable with this name. Is it really a Model?
I tend to call it "DbModel" or something to indicate that it is database related stuff.
And how do you guys call the entity class? I think I like the EF typical name "DbContext".
So within my controllers I´d have something like
public class WorldController : Controller
{
DbContext db = new DbContext();
public ActionResult Own()
{
var allContinents = db.Continents;
[...]
}
}
Sorry for being fussy but I really do care about naming.
It is good to care about naming!
How to do it depends on the composition your application. Let's say you have a web application for registering UFO sightings, to name something common. If there is a separate part of your db (maybe a separate schema) containing users, roles and permissions, you could create a context named AuthorizationContext, and for the business part a context named UfoDbContext.
I mean, if there are clear aggregates with no or little overlap you could create separate contexts for them with clear names. If one context fits the bill, I would still give it some meaningful name (not DbContext) that relates to your application domain.
There are people (I'm not one of them) that like to work with one context per application "column" (db to UI) or "user story". Meaningful names are even more important then.
My suggestion would be to use something that indicates the contents in the naming. You could take part of your project name, for instance, and bring it down into the name of the EDMX. Include something that makes it less generic.
I also tend to include an "Ef" in my naming, which I started when working on a project that already had an existing ORM.
To take Microsoft's prototypical example: if your project fell under the umbrella name of Norwind, here's how I would name some of the files in my model project:
EDMX File:
NorwindEfModel.edmx
Generator/TT File:
NorwindEfDbContext.tt
Entities class:
NorwindEntities
I can't say this is exactly how Microsoft would have it if you downloaded a sample project from them (though I believe it would be similar), but I think it's a reasonable naming structure and it fits my needs. The bottom line is this largely comes down to opinion and your need for specific distinction.
I've been going through the tutorials (specifically ones using Linq-To-Entities) and I understand the basic concepts, however some things are giving me issues.
The tutorials usually involve only simple models and forms that only utilize basic create, update and delete statements. Mine are a little more complicated, and I'm not sure I'm going about this the right way because when it comes time to handle the relationships of a half dozen database objects, the tutorials stop helping.
For the post method, the usual way of performing CRUD operations
entities.AddToTableSet(myClass);
entities.SaveChanges();
Won't do what I want, because a fully implemented class isn't getting posted to the controller method. I may post individual fields, form collections, or multiple DTO objects and then call a method on a service or repository to take the information I receive from a form post, along with information that it needs to query for or create itself, and then from all of those things, create my database object that I can save.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(int id, [Bind(Exclude = "Id")] ClassA classA,
[Bind(Exclude = "Id")]ClassB classB)
{
// Validation occurs here
if(!ModelState.IsValid)
return View();
try
{
_someRepositoryOrService.Add(id, classA, classB);
return RedirectToAction("Index", new { id = id });
}
catch(Exception ex)
{
// Logging and exception handling occurs here
}
}
public void Add(int id, ClassA classA, ClassB classB)
{
EntityA eA = new EntityA
{
// Set a bunch of properties using the two classes and
// whatever queries are needed
};
EntityB eB = new EntityB
{
// Set a bunch of properties using the two classes and
// whatever queries are needed
};
_entity.AddToEntityASet(eA);
_entity.AddToEntityBSet(eB);
_entity.SaveChanges();
}
Am I handling this correctly or am I bastardizing the framework? I never actually use an entity object directly, whenever I query for one I put the information I need in a DTO and base my Views off of that. Same goes with the creation. Is this allowed, or is my avoidance of using entities directly going against the purpose of using the framework?
Edit: I'm also worried about this approach because it requires empty constructors to properly do the LINQ queries because of this error message:
Only parameterless constructors and
initializers are supported in LINQ to
Entities.
This isn't a big deal since I rarely need logic int the constructors, but is this an issue to have no constructors and only public properties?
_someRepositoryOrService.Add(id, classA, classB);
I would say you couple your repositories with presentation layer. This shouldn't be. Your repositories should only work with entities. Next, notice how your Add method
public void Add(int id, ClassA classA, ClassB classB)
breaks Separation of Concerns (SoC). It performs two tasks:
map view data into entities
save to repository
Obviously the first step should be done in presentation layer. Consider using model binders for this. It can also help you to solve the constructors problem, since your model binders can be made aware of the construction requirements.
Check also this excellent post by Jimmy Bogard (co-author of ASP.NET MVC In Action) about ViewModels. This might help you to automate mapping. It also suggest a reversed technique - make your controllers work with entities, not ViewModels! Custom action filters and model binders are really the key to eliminate routine that that don't really belong to controllers but rather an infrastructure detail between view and controller. For example, here's how I automate entities retrival. Here's how I see what controllers should do.
The goal here is to make controllers contentrate on managing business logic, putting aside all the technical details that do not belong to your business. It's techical constraints that you talk about in this question, and you let them leak into your code. But you can use MVC tools to move the to them infrastructure level.
UPDATE: No, repositories shouldn't handle form data, that's what I mean by "coupling with presentation". Yes, repositories are in the controller, but they don't work with form data. You can (not that you should) make form work with "repositories data" - i.e. entities - and that's what most examples do, e.g. NerdDinner - but not the other way. This is because of the general rule of thumb - higher layers can be coupled with lower ones (presentation coupled with repositories and entities), but never low level should be coupled to higher ones (entities depend on repositories, repositories depend on form model, etc).
The first step should be done in the repository, that's right - except that mapping from ClassX to EntityX does not belong to that step. It's mapping concern - an infrastructure. See for example this question about mapping, but generally if you have two layers (UI and repositories) they shouldn't care about mapping - a mapper service/helper should. Beside Jimmy's blog, you can also read ASP.NET MVC In Action or simply look at their CodeCampServer for how they do mapping with IEntityMapper interfaces passed to controller constructors (note that this is more manual and less-work approach that Jimmy Bogard's AutoMapper).
One more thing. Read about Domain Driven Design, look for articles, learn from them, but you don't have to follow everything. These are guidelines, not strict solutions. See if your project can handle that, see if you can handle that, and so on. Try to apply this techniques since they're generally the excellent and approved ways of doing development, but don't take them blindly - it's better to learn along the way than to apply something you don't understand.
I would say using DTOs and wrapping the Entity Framework with your own data access methods and business layer is a great way to go. You may end up writing a lot of code, but it's a better architecture than pretending the Entity Framework generated code is your business layer.
These issues aren't really necessarily tied to ASP.NET MVC in any way. ASP.NET MVC gives basically no guidance on how to do your model / data access and most of the samples and tutorials for ASP.NET MVC are not production worthy model implementations, but really just minimal samples.
It seems like you are on the right track, keep going.
In the end, you are using Entity Framework mostly as a code generator that isn't generating very useful code and so you may want to look into other code generators or tools or frameworks that more closely match your requirements.