I recently, out of ignorance and lack of time, merged the domain models (POCO entity classes) from several projects into one 'DataModel' project, because I didn't want to duplicate dedicated DbContexts over all the projects. It struck me as ideal that something generic might be done, like a DbContext extension, to which one can add DbSet instances from various client projects.
I have read mention of such things, normally in the same circles as authors that contend - and I agree wholeheartedly - that the repository functionality is fulfilled completey by the DbSet class.
Can anyone offer any advice for building a generic DbContext which can exist in one project, where other projects can all have their domain models (sets of domain entities) registered with the shared DbContext, where they are all allocated they own DbSet to act as their repository?
building a generic DbContext which can exist in one project, where other projects can all have their domain models (sets of domain entities) registered
Interesting idea, but I'm not sure what you would gain by that.
For one, you'd never be able to simply type db.Customer (or similar). It should always be genericdb.Set<Customer>(), not knowing whether genericdb knows about Customer at all. (It may not have been registered).
Then, how should this registering take place? There are two ways to let a context map a class to a database model:
Creating a DbSet property in a DbContext-derived class and rely on code-first default conventions concerning table and column names, pluralization, etc.
Providing mapping configuration.
The first option defeats the purpose of a generic context class, so you'd have to register the domain classes by supplying EntityTypeConfiguration<T>s for each class in the domain, also for classes that normally could do without. (This should be done in the context's constructor, by the way.)
A further implication would be that somewhere you'd need a component/service that knows which groups of classes belong together and is able to deliver a coherent list of configurations. So, in stead of having dedicated contexts as an organizing principle out of the box you'd have to create your own organizer.
But back to the start. Couldn't you create a DAL that contains a DbContext factory that supplies the contexts as they previously existed for your projects? You don't have to duplicate dedicated DbContext classes this way.
Related
I'm aware that copying entity classes and properties into DTOs is considered anti-pattern, so by Exposed domain model pattern the same #Entity can be used as both database entity class, and DTO for service and MVC layer. (see here https://codereview.stackexchange.com/questions/93511/data-transfer-objects-vs-entities-in-java-rest-server-application)
But suppose we have microservice architecture where the same set of properties is used as entity in one project with persistence, and as DTO in another project which uses the first one as a service. What's the proposed pattern in such a situation?
Because the second project doesn't need #Entity related functionality, and if we put that class in shared library, it will be tied unnecessary to JPA specific APIs and libraries. And the alternative is to again use separate DTO classes anti-pattern.
When your requirements for a DTO model exactly match your entity model you are either in a very early stage of the project or very lucky that you just have a simple model. If your model is very simple, then DTOs won't give you many immediate benefits.
At some point, the requirements for the DTO model and the entity model will diverge though. Imagine you add some audit aspects, statistics or denormalization to your entity/persistence model. That kind of data is usually never exposed via DTOs directly, so you will need to split the models. It is also often the case that the main driver for DTOs is the fact that you don't need all the data all the time. If you display objects in e.g. a dropdown you only need a label and the object id, so why would you load the whole entity state for such a use case?
The fact that you have annotations on your DTO models shouldn't bother you that much, what is the alternative? An XML-like mapping? Manual object wiring?
If your model is used by third parties directly, you could use a subclassing i.e. keep the main model free of annotations and have annotated subclasses in your project that extend the main model.
Since implementing a DTO approach correctly, I created Blaze-Persistence Entity Views which will not only simplify the way you define DTOs, but it will also improve the performance of your queries.
If you are interested, I even have an example for an external model that uses entity view subclasses to keep the main model clean.
Thank you for the answers, but emphasize in the question is on microservice (MS) architecture and reusing defined entity POJOs from one MS in another as POJOs. From what I've read on microservices it's closely related to another question - should MSs share any common functionality and classes at all, or be completely independent? It seems there is no definite agreement on it, and also no definite answer, or widely accepted pattern, to this.
From my recent experience here is what I adopted, and it works well so far.
Have common functionality across MSs - yes, in form of a commons project added as dependency to all MSs, with its dependencies set as optional. Share entity classes (expose them in commons) - no.
The main reason is that entity classes are closely related to data store for particular MS. And as the established rule is that MSs shouldn't share data stores, then it makes sense not to share entity classes for those data stores. It helps MSs to be more independent, and freedom to manage their data store in their own way. It means some more typing to add additional DTO classes and conversion between them, but it's a trade-off worth taking to retain MS independence. Reasons Christian Beikov and Maksim Gumerov mentioned apply as well.
What we do share (put in commons) are some common functionality and helper classes (for cloud, discovery, error handling, rest and json configuration...), and pure DTOs, where T is transfer between MSs (rest entities or message payloads).
The design of EF forces developers to inherit the DbContext class. Some reusable libraries (such as ASP.NET Identity) typically provides its functionality using the same inheritance route, i.e. by providing the IdentityDbContext base-class.
But obviously this won't work if you have 2 such libraries, e.g. requiring you to inherit from IdentityDbContext and CmsDbContext at the same time, which is obviously impossible to do on .NET. The result that I want is to have an application-dbcontext that contains both the models from my identity module and my cms module (I won't be able to separate this to 2 dbcontexts since that would mean I will end up with multiple connections and transactions, and that my models can only reference to either identity or cms entities, but not both).
It's hard to believe that this question hasn't seemed to be asked around EF community, but this seems like a horrendously bad ORM design. Inheritance only lets you to have strictly linear modularisation. (As a comparison, in NHibernate, ISession and your Configuration are 2 separate things, therefore you can use discovery process to build up your mapping-configuration from different unrelated modules, without messing with my ISession and thus my db-connection/transactions).
So the question is, let's say you're a developer of a module that would like to register models into entity-framework (similar to ASP.NET identity module), you won't want to have a base DbContext that the consuming application must inherit, because it would prevent them from consuming other modules (e.g. ASP.NET identity's IdentityDbContext). So what are my options?
Is there any way to register models into a DbContext class without requiring to inherit from a DbContext? Is overriding OnModelCreating the only way to get access to a ModelBuilder?
I don't think your comparison is entirely fair. (Although I'm the first to admit that NHibernate beats EF in many areas).
With NHibernate, usually you load objects by some generic method in which you supply the type you want to load. You could create ISession implementations with hard-coded Query<T> (or QueryOver<T>) properties, like...
public Query<MyUser> Users { get; set; }
...and you'd have the same "problem" that you can't merge, or inherit from, two different implementations.
Likewise, you could work with EF by loading objects by using context.Set<T> only. You could even inject the configuration (sort of) by supplying EntityTypeConfiguration classes (as a list) in the context's constructor, storing them in a member variable and adding them to the model builder in the OnModelCreating override.
These specialized context classes, like IdentityDbContext, are offered to make life easier if they suit you. They have hard-coded DbSet properties (among others). The fact that you can't multiple inherit them is not a design flaw. It's just a (non-negotiable) language specification.
Choose the one that most closely serves your needs (propably CmsDbContext) and add other class mappings yourself.
Description:
I've tried to separate certain domain segments into different DbContexts.
Each has several DbSets, but there are some DbSets that are shared, for example the UserProfile.
The reason for this separation is the speed at which the model is generated and the simplicity (less sets in an object, helps with intellisense).
However, I am not sure about what exactly belongs to the model that is generated.
Q1: Is every entity that is transitionally connected with the entities, for which a DbSet exists in a DbContext, included in the model?
Q2: If so, would that mean that performance-wise it serves no purpose to separate the domain into different contexts, since everything that is connected ends up in the model anyway, no matter which DbSets are stated in the DbContext?
Where can I find more information on how the model is generated? I've read a book on EntityFramework and CodeFirst and couldn't find that specific information...
Answering your first question: yes, all relations are modeled including the entities on both sides, so every entity that's connected by a navigation property to an included entity will also be included in the model regardless if there's a DbSet for it or not.
Entity Framework doesn't force you to create DbSets for all entities. This can be handy if you want to "restrict" child entities to only be accessible through their parents.
Regarding your second question: separating your contexts might still improve performance, if not all entities belonging to one context are reachable via navigation properties of entities belonging to the other context. There could be an additional cost associated with explicitly including more DbSets in a context, too.
You could read (some parts of) the Entity Framework source code, it's open-source and available on CodePlex to learn more about how the model is built.
My application is broken down into several assemblies.
The MyProject.Infrastructure assembly contains all of the Domain objects such as Person and Sale as well as interfaces repositories such as IPersonRepository and ISaleRepository.
The MyProject.Data assembly contains concrete implementations of these repositories.
The repositories pull data from a database and instantiate new domain classes. For example, IPersonRepository.GetPersonByNumber(customerNumber) will read a customer from the data source, create a new Person class, populate it and return to the caller.
I'm now starting to see cases where adding some methods to my Domain classes might make sense, such as Person.UpdateAddress(address).
Is it ok to put this method on my Person class as a virtual method, and then create derived classes inside my Data layer which override those methods to provide the desired functionality?
I want to make sure I'm not going breaking any DDD conventions.
I know I also have the option of putting these methods on the repository - e.g. IPersonRepository.UpdatePersonAddress(person, address).
Person.UpdateAddress should definitely be in your domain, not in your Repository. UpdateAddress is logic and you should try to avoid logic inside your repository. If you're working with Entity framework there is no need for 'data classes'.
Most ORMs have change trackers which will persist related entities automatically when you persist the main one (provided you declared the right relations in the mapping configuration), so you don't need UpdatePersonAddress() on your Repository. Just do whatever you want to do at the object level in Person.UpdateAddress(address) without thinking about persistence, this is not the place for that.
What you need though is an object that will be called in execution context-aware code to flush changes to the persistent store when you think it's time to save these changes. It might be a Unit of Work that contains the Entity Framework DbContext, for instance.
I use standard ObjectContext and EntityObjects in my application. Let's say two of my tables are Projects & Services. Projects have Subproject (from Projects table with ParentID == ProjectID) and also Services. So I would have a hierarchy like Projects->Subprojects->Services. But I need to inherit Projects and Services from an abstract base class so I can use any of these entities as a new Task/Job entity in my application. Then, for example I can create a TreeList listing all Tasks (either a Project or Service). Is there anyway in EDMX designer I can create a new type (entity) which is the base calss for two or more concrete types?
It is possible with TPC inheritance but it will include a lot of complication to your design. For example:
you will have to move shared properties to the base class
you will probably have to maintain some mappings manually in EDMX (at least I had when I did the sample on screenshot)
you will have only single ObjectSet<Tasks> and you will have to use OfType to query only Projects or Services
you will have to use unique Id per Task = across both Project and Service tables (can be achieved by correctly configured identities in database)
It will look like:
Another option is using interface on your entity objects instead of parent class. You can define interface in your partial part of entity object and handle retrieving both Projects and Services by yourselves where your UI will expect only list of types implementing your interface.
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/01/25/table-per-concrete-type-inheritance-in-entity-framework.aspx
Since it sounds like your data is coming from 2 separate tables, Projects and Services, no, I don't think you can achieve this in the designer (at least, not without hand-editing the generated edmx). If there were a common table to represent the base class, that could be done in the designer, but that doesn't sound like it fits your situation.
What you may be able to do is use an interface instead of an abstract base class, and use partial classes in your entity model to implement the interface for each of your entities. You can't directly inherit from your abstract base class in your entity model, because all of your entities already derive from EntityObject. If you have a lot of shared implementation that resides in your base class, it might be worthwhile to switch to POCO, where you can define your own inheritance hierarchy.