I'm having some difficulty getting my two contexts that use the same database to cooperate. Here's the scenario:
In an MVC application using EF 6 Code-First, there is one database with two contexts.
- The first context is the ApplicationIdentity context with a customized ApplicationUser object.
- The second context is the business context, which holds a Team model:
public class Team
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public ApplicationUser TeamLeader { get; set; }
public string Name { get; set; }
public virtual ICollection<ApplicationUser> TeamMembers { get; set; }
public bool IsActive { get; set; }
}
Managing the migrations has been difficult, though this answer has proven extremely helpful: Multiple DB Contexts in the Same DB and Application in EF 6 and Code First Migrations
The problem is that the Identity context keeps trying to create the Team table in it's migrations, and then the Business context keeps trying to create duplicate ApplicationUser records when a new team is created, populated, and saved.
What I would like is for the following rules to be applied:
The IdentityContext is responsible for creating and altering the schema of the Identity tables only. It has no knowledge of objects (aka Team) outside of it's area of responsibility.
The Business Context is responsible for referential integrity between it's objects and the IdentityObjects, but it may not edit records in the Identity tables. If a user does not exist, error, don't create.
Does anyone have any tips on how to get these contexts to play nice with each other? I really don't want to break the referential integrity between Identity objects and business objects.
What you're trying to do looks like "DDD Bounded Contexts".
It's a bit long to explain how to use them, but here are some tips:
use modelBuilder.Ignore<EntityType>(); to exclude from your model related entities that are automatically added to your context
use different classes in each model where necessary, and map them appropriately. I mean classes that map only part of the columns. Use modelBuilder to configure them
use readonly navigation properties and readonly properties where necessary
This is a very interesting post by Julie Lerman: Data Points - Shrink EF Models with DDD Bounded Contexts
Related
Let's define Term as a principal entity and Course as a one to many dependant relationship.
public class Term
{
public int Id { get; set; }
public List<Course> Courses { get; set; } = new List<Course>();
}
public class Course
{
public int Id { get; set; }
public DateTime EndDate { get; set; }
}
A common query criteria for our Term entity is to check whether all of the courses are finished or not and by that we deem the Term as finished or not too, and this implicit state can show itself in a lot of places in our bussiness logic, simple queries to populate view models, etc.
Using ORMs like EntityFramework Core this query can popup in a lot of places.
Terms.Where(t=>t.Courses.All(c=>c.EndTime > DateTime.Now))
Terms.Count(t=>t.Courses.All(c=>c.EndTime > DateTime.Now))
Other examples of this that come to mind are a product and its current inventory count, posts that only contain unconfirmed comments, etc.
What can we consider as best practice if we are to capture these implicit states and make them directly accessible in our principal entity without the need to rehydrate our dependant entity from the database too?
Some solutions that come to mind:
Using a computed column to do a subquery and map it to a property on the principal entity e.g. Term.IsFinished
Defining a normal property on our entity and use a scheduling solution to update its value on predetermined timestamps which is not acceptable in a lot of cases due to inconsistency in different intervals, or use domain events and react upon them to update the property on the principal entity
Create a view, with the two tables joined and aggregated per principal entity.
Use the view directly in Entity Framework instead of the base table.
For bonus points:
In SQL Server you can create a clustered index on the view, and it will be automatically maintained for you. Oracle has a similar concept.
In other RDBMSs, you would need to create a separate table, and maintain it yourself with triggers.
I have multiple projects that return the same OData entities through a API endpoint. Now i want to call all of the projects and store them in my calling projects database with entity framework.
To add them to the db the ID gets overwritten but i want to save the id that the entity has in the projects database as well. so i can still access them if need be and to check if the data isn't already in my database. Because of this i need to add another MainProjectID and projectID column to the entity.
I tried making a new class that has a reference to the entity i want to save but this used new id's for the entities. I also tried inheriting the class but this gave me key conflict issues, and generics don't work either in entity framework(i'm not saying they should). So i'm kinda at a loss right now.
I basically want to save the id as a non-key. Is there any way i can do this without writing entirely new classes and parsing them manually ?
Any help would be greatly appreciated.
We have multiple alternatives here:
In a distributed system, best way to cope with these kinds of ID clashes is to make IDs globally unique. If you can modify how IDs are generated, that would be my choice to go. You can use a UUID (or Microsoft implementation GUID) that will produce a universal unique identifier. Or if that seems like an overkill you can devise a simple mechanism that combines ID with projectID. However you should ensure that the method you will use will not produce any collisions (no two different id-projectId pair will map to same value).
This will ensure that same entity is used throughout your application and no overlaps occur if you try to put records from different sources into the same table. You only need to implement a mechanism to record which ID originated from which source. You can use a reference entity at aggregator for this purpose. You also need to disable auto increment nature of the ID column so that your global unique values are used in table.
You can use different entities for producing and aggregating applications. I don't know your application, but that seems like an OK approach to me since the aggregating application has a different idea about the entity. The aggregating application cares for which application produced the entity, that might make putting the source application identifier into the entry justifiable. Your entities will only differ in that and when you receive the OData object from API you'll need copy all other properties and put project identifier yourself.
You can use the previous solution, but you can use a derived class in order to not to repeat your object properties. This is a better design alternative. However with this method you'll have some problems with the primary key (as you've stated you had). Consider this example
public class Base {
public int ID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Name")]
public string Name { get; set; }
}
public class Derived : Base {
[Key]
public int projectId {get; set; }
}
If you don't put [Key] to Derived then you'll have only ID as primary key. When you put [Key] to Derived then you'll have only projectId as primary key. You need to define a composite key and you can do this by removing the [Key] annotation from projectId and using the onModelCreating override of DbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Derived>().HasKey(a => new { a.ID, a.projectId })
.Property(c => c.ID).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
modelBuilder.Entity<Derived>().Property(c => c.projectId).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
}
You can mix these alternatives. You can drop the primary key on ID field, and then you can insert a new Entity that will model 1-M relationship between ID's and project ID's.
It is my first time in DDD. In company we don't have "domain master". I have only read about DDD I need to implement domain with DDD aproach.
So, I know that in domain there are no place for Database features. But if I would use my domain with Entity Framework and NOSQL database. With EF i need to make collections virtual and in constructor alloce as new. This is bad in DDD?
My code:
public abstract class Merchant : AggregateRoot
{
public Company Company { get; set; } // Entity
public string CIF { get; set; }
public string NIP { get; set; }
public string Status { get; set; }
public Address Address { get; set; } // Entity
public Group Group { get; set; } // Entity
public virtual ICollection<Brand> Brands { get; set; } // Brand is entity
protected Merchant()
{
this.Brands = new List<Brand>();
}
}
There are multiple shades of opinion about that issue in the DDD space.
To me, the primary measure of "persistence ignorance" is :
Will a change in my database break things in my domain layer, forcing
me to open up the domain model and modify stuff to fix it ?
If we look at your example, the answer is clearly no.
It would have been the case if you had for example data annotations in your entity class referring to table or column names, or if you relied on mapping by convention and changed the Merchant table name to Reseller in the DB. But having a default constructor and virtual property doesn't make your domain class more fragile in the face of database changes.
Then you have a secondary question, a less critical one IMO :
Is the ORM a hindrance in my implementing domain entities just the way I
want and as DDD-compliant as they need to be ?
This one is a bit more challenged. It might be, if the ORM forces you to add operations that can leave the domain object in an inconsistent state. I wouldn't consider a parameterless constructor as prone to that though, since it can be private and thus impossible to shoot yourself in the foot with. Same with setters.
Some consider that small traces such as the need for virtual and parameterless constructor violate DDD, because your entities are not pure any more, they contain oddities caused by the presence of an ORM. Therefore, you should create a second "persistence" model to leave the domain model untainted. I don't. I think most of the time it's not worth the tradeoff in terms of complexity - you can live with the small quirks as long as the first rule of persistence ignorance holds.
I would be more concerned about having public setters than a protected default constructor or a virtual property. The problem with that is can lead to an inconsistent state of the entity. For example, you may want to validate the address properties to make sure all the required properties are set and the postal code corresponds to the state/country. Another example would be status transitions; once the entity reaches a "final" status, it cannot be changed anymore.
While you can create separate validators for entities and use them before you persist the entities, it defeats the purpose of a rich domain model.
There are a few ways to get around it. You can create DTO objects that mirror the database schema and use hydrators to populate the entities (with protected/internal property setters) from those DTOs assuming the data in the database is always in the consistent state. All the new changes will have to go through entity methods to get validated. Then you would hydrate the DTOs based on the latest entity data and persist it.
CQRS with event sourcing is a more advanced alternative of this that persists all changes as an immutable log/event-store rather than (only) the latest data snapshot. But that is not something that is necessary for every domain scenario.
Currently I have a nice model, and I can generate a database based on that, but from what I can tell, the tables are never created (leading to all sorts of fun runtime errors).
My understanding is that there are three options for code first that would force EF to create the tables for me:
DropCreateDatabaseAlways
CreateDatabaseIfNotExists
DropCreateDatabaseIfModelChanges
How can I use these if I am doing things model first?
Additionally, is this an expected error, or when I selected generate database from model the first time is this supposed to happen automatically?
Edit: I tried calling
context.Database.Initialize(true);
context.Database.CreateIfNotExists();
and nothing changes.
also this is good toturial
tutorial
but if you made the model good the first time you access the dbContext the db should be created by the db strategy which you can set: Database.SetInitializer()
set initializer
in short after you create your model you need to create class that inherit from DbContext:
public class CompanyContext : DbContext
{
public CompanyContext() : base("CompanyDatabase") { }
public DbSet<Collaborator> Collaborators { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Manager> Managers { get; set; }
}
and then when you access this context the tables should be generated.
you can also seed the database with data you should inherit from the strategy you want to implement look at this link seeding database
What is the difference between a "model" and a "context" in Entity Framework jargon?
I'm using the Entity Framework database first approach in an application. These terms have come up many times as I've been reading different forums and articles on EF implementation strategies. I can't seem to figure out how these two are different (not even with just entity framework, but with software development in general). People use the words as if they are different, but then some people seem to use the words interchangeably.
Context
This is easy. The context is either the DbContext or the older ObjectContext class that is the core of the entity framework data access layer. It supplies transparent database access through strong typed sets of entities, tracks and saves changes, manages database transactions and connections, and contains a number of utility methods to facilitate all kinds of data access tasks (esp. DbContext).
Model
This can be two (or three) things.
The data model, or store model. Which is the relational model of the database underlying the EF data access layer.
The conceptual model, or class model. Which is the .Net class model that represents the database. This model can either be generated by EF (database-first) or it can be an existing class model (code first). The conceptual model and the store model are linked through mapping, so EF knows how to populate .Net classes from database records and, conversely, how to save .Net classes to the database.
Some people refer to the classes in the conceptual model as "models". This is not wrong, but I prefer to use the name entities for this.
So context and model are two quite different things. You might say that the context is the middleman between two different types of models.
Loosely speaking a context relates to a database connection or session wherea the model is the mapping between tables, views, etc to data access object classes (i.e., objects that will contain the data)
A model is a class which usually represents a database table or structure to display a database table. For example, if I had a database for cars, then a model for car could be
public class Car
{
[Key]
public int CarId { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
}
This model is used by entity framework and the sql provider (for mysql or mssql usually) to compose a query against a database. The query requires a way for this to be mapped, and that is the job of the context. The context usually extends DbContext and is what is used for the facade of accessing the database table as an in memory object.
public class CarContext : DbContext
{
DbSet<Car> Cars { get; set; }
}