I'm trying to create EF code first with multiple contexts.
One context for for StaffContext (HR) and the other is ,ShippingContext.
Is the idea of having multiple contexts has any advantages ? Cause I feel it is complex to construct.
How do we construct the entities ? Define all in base context or in each separate context ?
In these contexts, I need access to Staff entity which when I try to "update-database" will gives me an error since the Staff entity already exist in other context. Is the fact that I have same entity in different context is wrong design ?
This is what I have at the moment :
public class StaffContext : BaseContext<StaffContext>
{
public DbSet<StaffPosition> StaffPositions { get; set; }
public DbSet<Staff> Staffs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
public class ShippingContext : BaseContext<ShippingContext>
{
public DbSet<Armada> Armadas { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Shipment> Shipments { get; set; }
public DbSet<ShipmentDetail> ShipmentDetails { get; set; }
public DbSet<ShipmentHandler> ShipmentHandlers { get; set; }
public DbSet<ShipmentOrder> ShipmentOrders { get; set; }
public DbSet<ShipmentOrderDetail> ShipmentOrderDetails { get; set; }
public DbSet<Staff> Staffs { get; set; }
public DbSet<Pangkalan> Pangkalans { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Thanks a lot in advance.
I don't really know why you would want to do that in the first place - having one context you just recreate whenever it is needed is much better and easier in my opinion. However, lets start:
To 1:
Multiple contexts can be easier to maintain, because it just splits up code more over multiple objects - if you have problem with one context, you can simply look at the model of it and fix the problem. However, your context shouldn't be too complex anyways.
Multiple contexts do have the advantage that each of those does not become too big most of the time, which will bring a performance gain. However, you will throw away EF functionality whenever you try to cross context boundaries, like query creation for joins and relationship fixups.
When you access multiple databases with differing schemas or the need for differing models, multiple contexts are the way to go. Also, whenever you do update operations on your database (with SQL, not migrations) you will need multiple contexts to access the different manifestations of updated entities.
To 2:
You can't have the same entity in multiple contexts at the same time. This does also mean that you don't have to provide the DbSet's for those entities already contained in another context, unless you can guarantee you will not touch the same objects with differing contexts.
When you don't have the DbSets for a entity set, of course you won't need the model configuration for this entity in this context. However, general stuff like conventions and datatype mapping can be done in a base context. Also, this might be the best place for context-related help functions.
To 3, although already mentioned:
There can be a place for multiple contexts, but I feel like this should be an exception. When you have multiple contexts, you
will run into concurrency errors far more often (since you might change the concurrency items to the same values in different contexts)
cannot access EF functionality across those boundaries (like navigation properties, since you can't keep objects of those types in your context inclusively) and
can't use the Update-Database/Migrations functionality unless you run the risk to define all entities in both contexts.
I don't feel like it is generally a bad design, however it does bring some problems you will have to overcome, while having all objects in one context does not have many disadvantages, if any.
Related
Problem: Save same kind of aggregated statistics for web api calls for different time units (hour, day etc.).
All the aggregated information will contain the same kind of information. Something along the lines of:
public class AggregatedStatistics
{
public DateTime TimeStamp { get; set; }
public int Hits { get; set; }
public int CachedHits { get; set; }
}
Since I would like to aggregate stats for different time units I would like to keep each time unit in a separate table. Reason being that it would a) make lookups faster and b) less risk of accidentally using wrong data. I am not experienced with databases so I do not know if either point really is a concern. I guess the latter should not be, and the former depends on the amout of data.
So, what is a good way to accomplish what I am after? I guess one solution that might work is to make the above class abstract and inherit from it (if that would work in EF Code First). That seems kind of semi-ugly though since no more members would be added to the class.
Below is the Project code-first class mapped directly to the database through the Entity Framework 6 Fluent API:
public class Project
{
public Project()
{}
public int ProjectId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public ICollection<ProjectVersion> ProjectVersions { get; set; }
}
Anemic models in Domain-Driven Design are an anti-pattern. I want to use this same class in my domain model instead of creating a separate Project domain class and having to perform complicated mapping between the two in the repository (and with the hundreds of other models we have).
This is how Project would look as a domain model class:
public class Project
{
private readonly List<ProjectVersion> projectVersions;
public Project(string name, string description)
{
Name = name;
Description = description;
projectVersions = new List<ProjectVersion>();
}
public int ProjectId { get; private set; }
public string Name { get; set; }
public bool IsActive { get; private set; }
public IEnumerable<ProjectVersion> ProjectVersions
{
get
{
return projectVersions;
}
}
public void AddVersion(ProjectVersion version)
{
projectVersions.Add(version);
}
}
From what I have read, I am able to map to a private fields with EF's Fluent API.
Are there any any shortcomings here? Am I taking an unnecessary shortcut?
The only problem I can forsee is when a business domain model would essentially consist of data from two or more data entities.
I think you're making a mistake in this approach. I think you should separate the concerns of your Domain models from the concerns of your Entity models. Uncle Bob wrote a strange, but on-point blog post about this here: Dance You Imps! (seriously, it's a weird post.) The ORM's job is to act as a contract to your database. Your domain models' job is to provide the functionality. In short, you should let Entity Framework function the way it wants to. If you want to do DDD, write a mapping layer to convert EF models to your Domain models.
Are there any any shortcomings here?
Possibly.
It is true that EF can address private members, so it is able to materialize a Project with a loaded ProjectVersions collection if you want. It won't use the AddVersion method for that (it doesn't even know it exists), but it will add objects to the projectVersions member.
In the application code you want to add versions through a method. There may be some problems with this AddVersion method though.
You can always add a ProjectVersion, but you will never be sure whether it will be stored, because for EF to track the addition projectVersions must have been loaded. However, you don't want a domain entity to be responsible for loading its own children from the database. So AddVersion gives the class a responsibility it can't fulfil to the full.
Calling AddVersion can occur any moment during the lifespan if the object. Usually this will be longer than the lifespan of the context by which it was created and tracked. So you can't rely on lazy loading to come to the rescue if the collection is not loaded yet. (ProjectVersions should virtual ICollection for that, by the way).
The conclusion is that you always have to load projectVersions eagerly (through Include) for AddVersion to be guaranteed to work properly. So there is a dependency in your application between two not obviously related pieces of code, which is a potential source of bugs.
When it is time to save the Project, you have to attach it to a context and find out which ProjectVersion should be marked for insert and which for update (and there's not even a RemoveVersion method yet.
All in all, it is much simpler to add versions in a service method that does all required actions within the lifecycle of a context. An added version will be marked for insert automatically. Likewise, any updated and deleted version will be marked correctly.
I'm just now learning MVC4 and Entity Framework. Some examples I have seen have all the "DbSet"s in one class, other I have seen each model have the DbSet in it. Is there an advantage of one way or the other? I kinda like having ONE "MyDbContext" model that references all the other models, but not sure which is better. Any thoughts and real life issues with either way?
public class UsersContext : DbContext
{
public DbSet<UserProfile> UserProfiles { get; set; }
}
public class UsersPostsContext : DbContext
{
public DbSet<UserPost> UserPosts { get; set; }
}
Verses:
public class MyContext : DbContext
{
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<UserPost> UserPosts { get; set; }
}
The first example is definitely not the way to go.
It defeats the power of EF to handle complex object graphs. What if you want to retrieve users and their posts and profiles from the database? (Just a random example). You'd need three contexts and a lot of cunning to put the right objects together. And that's only the reading part. CUD actions are even more complex, if only the logic you need to do inserts/deletes in the right order and set FK associations.
That does not necessarily mean that, consequently, you should always have one context class. It can be beneficial to have several of them for parts of the database that logically belong together and are relatively isolated from other parts (like authorization tables, CRM tables, product tables, reporting, ...). In this case you may decide to use bounded contexts.
I use the second notation because that context is more flexible to use. You don't have to wonder which object to pass to the service for example. You don't have to manage a numer of files so it is easier to understand database schema.
I am using VS 2010 and Entity Framework code first (version 6). I have two entities each in its own context and I want to create a one-to-many relationship between them.
Context 1 has the following entity:
public class MyTrust
{
public int MyTrustID { get; set; }
public string MyTrustName { get; set; }
}
and Context 2 has the following entity:
public class MyLocation
{
public int MyLocationID { get; set; }
public int MyTrustID { get; set; }
public virtual MyTrust MyTrust { get; set; }
}
with the following Fluent API
modelBuilder.Entity<MyLocation>()
.HasRequired(m => m.MyTrust);
The migration file for Context 2 contains the correct keys but also creates a new table for MyTrust which already exists in the other context.
I know that I can edit the migration file but that is not a solution.
My question is, how to I stop the creation of the second MyTrust table.
UPDATE
There was a major flaw above in that I pasted the wrong code into Context 2. Now corrected. Apologies.
You are working with so-called bounded contexts. The benefit of such contexts and how to work with them is explained in this blog by Julie Lerman.
The problem you experience, none of the contexts can be used in migrations, is addressed in this part:
If you’re doing new development and you want to let Code First create or migrate your database based on your classes, you’ll need to create an “uber-model” using a DbContext that includes all of the classes and relationships needed to build a complete model that represents the database.
Note that you can share the MyTrust type between all contexts, if you observe these rules (from Lerman & Miller's book DbContext, p 233):
An entity can only be attached to one context at a time. This architecture works
best with short-lived contexts where the instance to be shared will be completely
disassociated from one context before it is attached to another.
Entities that are attached to different contexts cannot be attached to one another.
UPDATE
In EF6 you can use multiple contexts for one migration path. See this walkthrough.
I'm a little overwhelmed with all of the information on DDD, unit of work, domain services, app services, etc. I'm trying to figure out how a persistence-ignorant domain model ultimately gets persisted, specifically in the context of unit-of-work and Entity Framework. Let's say I have an Order aggregate root, which I am attempting to keep in my persistence-ignorant domain model (the core of my architectural onion):
public class Order : EntityBase
{
public int Id { get; private set; }
public int MarketplaceId { get; private set; }
public int CustomerId {get; set;}
public List<OrderItem> Items { get; private set; }
public List<OrderComment> Comments { get; private set; }
public void AddItem(OrderItem item) { /**add item**/ }
public void AddComment(OrderComment comment) { /**add comment**/ }
public override bool Validate() { /**validate**/ }
public void Cancel() { /**cancel**/ }
}
Let's say I have a process that updates a property on the Order entity, for example it changes the CustomerId associated with the order.
I have an IOrderRepository in my domain layer, which would have an implementation (in an outer layer) with a function like this:
Order GetOrder(int orderId)
{
//get entity framework order, items, etc.
//map to domain-layer order and return domain-layer order
}
void UpdateOrder(Order order)
{
//get ENTITY FRAMEWORK order, order items, order comments, etc.
//take DOMAIN order (passed in to this function), and update EF items fetched above
//use a single EF unit of work to commit these changes
}
There's something wrong with my approach. The UpdateOrder function seems heavy for a small change; but it also seems I have to do that if my repository isn't aware of which items on the persistence-ignorant domain model have changed. Should I be handling every type of update in a separate repository function? UpdateMarketplace(int marketplaceId), UpdateCustomer(int customerId)?
As I'm typing this, I'm also wondering...maybe the way I have it above is not too heavy? If I change one property, even though I'm doing all of the above, perhaps Entity Framework will recognize that the values being assigned are the same and will only send the one db column update to SQL?
How can I take my Order domain model (fetching is straightforward enough), perform some operation or operations on it that may be limited in scope, and then persist the model using Entity Framework?
You need to look into the Unit of Work pattern. Your UoW keeps track of the changes, so when you get your order from your repository and modify it, you call UnitOfWork.SaveChanges() which should persist all the changes.
Using Entity Framework, your DbContext is basically the Unit of Work but I would create a simpler interface around it so you can abstract it away for easier usage in your higher layers.
Regarding EF, I would recommend mapping your domain entities directly using the code first approach. I would also turn off lazy loading and all the magic stuff so you have full control and less "surprises".
Unfortunately I'm not allowed to share our code but we have all this working pretty effectively with the new EF6 Alpha 3. I would recommend you taking a look at Microsoft Spain's nlayerapp for some implementation examples. I don't agree with many of their design decisions (also, see this review), but I think you can draw some inspiration from the Entity Framework parts. Take a look at their Unit of Work implementation and especially how they have abstracted it away for easier usage in the higher layers, and how they use it in their application services.
I will also recommend looking into creating a generic repository to avoid duplicating lots of logic in your aggregate specific repositories. MS Spain has one here, but you should also take a look at this thread.
Please have a look at this SO question where I gave an example of how I've implemented UoW & Repositories.
As #Tommy Jakobsen told you, your domain entities should be your EF entities, it would avoid you to add a useless mapping layer.
Hope that helps!
You may check ASP.NET Boilerplate's Unit Of Work implementation: http://www.aspnetboilerplate.com/Pages/Documents/Unit-Of-Work
It's open source project, you can check codes. Also, you can directly use it.