I have read and seen few projects that talks about splitting or multiple DbContext and I'm not sure what is the best practice.. should I create each DbContext for each entity or have all entity in one DbContext?
this is what I have for now.
public class PersonsContext : DbContext
{
public PersonsContext() : base("name=EmployeeContext")
{
}
public DbSet<Person> People { get; set; }
}
public class OrderContext : DbContext
{
public OrderContext() : base("name=EmployeeContext")
{
}
public DbSet<Order> People { get; set; }
}
Actually you don't need have to create one DbContext for each Entity. But you can have multiple DbContext for a single database. For an example let's say you want to separate your business aspect and security aspect of the application into two different modules. Then of course you can have two different context such as SecurityContext which has all the entities related to Security and BusinessContext consists of Business related entities.
Ex:
public class SecurityContext : DbContext{
public PersonsContext() : base("name=securitycontext"){
}
public DbSet<User> User { get; set; }
public DbSet<Role> Role { get; set; }
public DbSet<Group> Group { get; set; }
}
public class BusinessContext : DbContext{
public OrderContext() : base("name=businesscontext"){
}
public DbSet<Order> Order { get; set; }
public DbSet<OrderLine> OrderLine { get; set; }
public DbSet<Customer> Customer { get; set; }
}
Related
I work on a EF Core project for WPF app.
We decide to split the DbContext in 2 smaller Dbcontexts: (the project contains a single Database)
public class FirstDbContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DBSet<Parameters>{ get; set; }
}
public class SecondDbContext: DbContext
{
public DBSet<User>{ get; set; }
public DBSet<Books> { get; set; }
public DBSet<Parameters>{ get; set; }
}
and we keep a "super" DbContext (which contains all the DbSets from the DB) to maintain and migrate the DB
public class SuperDbContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DBSet<User>{ get; set; }
public DBSet<Books> { get; set; }
public DBSet<Parameters>{ get; set; }
}....
The first step to refactor code is to replace the lines which references the "SuperDbContext..." with the correct call "SecondDbContext.Books..."or "FirstDbContext.Post"... OK
Question:
In the Client app, the choice of DbContext is depending about a user's choice when app is launching: if user choose option1 => FirstDbContext, and if option2 => SecondDbContext.
How can we write the code to switch on the current DbContext to manage the "common DbSet" (Parameters) : before refactoring we have for example:
SuperDbContext.Parameters.FirstOrDefault()...
and now? do we have to write something like this:
if(option1)
{
FirstDbContext.Parameters.First()
}else
{
SecondDbContext.Parameters.First()
}
And what is the impact in the repositories? cause if we maintain this approach we have to duplicate code in the 2 Repositories?
No no... Forget about the approach you mentioned, you'll end up writing twice the code you need. Why don't you just use db context type :
At the beginning of your function, a single if else :
DbContext context;
if(option1)
{
context = new firstContextEntities();
}
else
{
context = new secondContextEntities();
}
And as both of your contexts are almost exactly the same, you will use your context by casting it to the greater one (the one that has the most access) :
var FirstLine = ((secondContextEntities)context).Parameters.First();
I have two DbContext class and some Entities in them. I know this is not good idea to have more than one DbContext but i have to do a lot of works to change my code! so my question is what is the best scenario for add relationship between two Entities with different DbContext?
For example an one to many relationship between User Entity with IdentityDb Context and Comment Entity with SiteDbContext :
public class User : IdentityUser
{
public DateTime JoinDate { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this,DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
}
public class IdentityDb : IdentityDbContext<ApplicationUser>
{
public IdentityDb() : base("DefaultConnection", throwIfV1Schema: false)
{
}
public static IdentityDb Create()
{
return new IdentityDb();
}
}
public class Comment
{
public int CommentId { get; set; }
[Required]
[StringLength(900)]
public string CommentText { get; set; }
[DataType(DataType.Date)]
public DateTime CommentDate { get; set; }
}
public class SiteDb: DbContext
{
public SiteDb(): base("DefaultConnection")
{
}
public DbSet<Comment> Comments{ get; set; }
}
Short answer: Entity Framework currently doesn't support creating a query which uses more than one context.
For work around: Refer this.
I have two to be related entities as below :
public class VehicleExtraEntity
{
public int Id { get; set; }
public Guid NameKey { get; set; }
public virtual ICollection<WordEntity> WordsOfName { get; set; }
}
And the other entity :
public class WordEntity
{
public int Id { get; set; }
public string Content { get; set; }
public Guid Key { get; set; }
}
My purpose is write multi language supported db tables. For example ;
WordEntity1 : {Id=1, Content="Child Seat", Key="abcdef-12456"}
WordEntity2 : {Id=2, Content="Çocuk Koltuğu", Key="abcdef-12456"} --> Same Key
VehicleExtraEntity1 : {Id=1, NameKey = "abcdef-123456"}
I have tried fluent api but that support only relationships with navigation property. And it wants to me use many to many relationship. But I want resolve my problem as I wrote as above.
Im using mvc5 with codefirst and the user account stuff.
I have a simple requirement a user can belong to multiple stores and a business can have multiple stores.
So far I have the business - many stores working but I cant seem to figure out how to setup the users.
My StoreModel
public virtual Business Business { get; set; }
public virtual ICollection<ApplicationUser> Employees { get; set; }
My BusinessModel
public virtual ICollection<StoreModel> Stores { get; set; }
Within my context I have tried
public class ApplicationUser : IdentityUser
{
//a user can belong to multiple stores
public virtual ICollection<StoreModel> Stores { get; set; }
}
however when I try add-migration the code generated is going to change my table names and does create the join table between Store & AspNetUser
My migration looks like
public override void Up()
{
RenameTable(name: "dbo.Stores", newName: "ApplicationUserStoreModels");
DropForeignKey("dbo.Stores", "ApplicationUser_Id", "dbo.AspNetUsers");
DropIndex("dbo.Stores", new[] { "ApplicationUser_Id" });
CreateIndex("dbo.ApplicationUserStoreModels", "ApplicationUser_Id");
CreateIndex("dbo.ApplicationUserStoreModels", "StoreModel_StoreId");
AddForeignKey("dbo.ApplicationUserStoreModels", "ApplicationUser_Id", "dbo.AspNetUsers", "Id", cascadeDelete: true);
AddForeignKey("dbo.ApplicationUserStoreModels", "StoreModel_StoreId", "dbo.Stores", "StoreId", cascadeDelete: true);
DropColumn("dbo.Stores", "ApplicationUser_Id");
}
Can anyone help what I need to do to get this working?
you can either just not have a store table and put a list in each appuser and business and EF will make your many to many relationship or you can use fluent api to map everything. Should be something like the following.
public class Business
{
public virtual ICollection<StoreModel> Stores { get; set; }
}
public class ApplicationUser : IdentityUser
{
public virtual ICollection<StoreModel> Stores { get; set; }
}
public class StoreModel {
public string ApplicationUserId { get; set; }
public int BusinessId { get; set; }
public virtual Business Businesss { get; set; }
public virtual ApplicationUser ApplicationUsers { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{ base.OnModelCreating(modelBuilder);
modelBuilder.Entity<StoreModel>().HasKey(e => new { e.ApplicationUserId, e.BusinessId});
}
I'm producing a simple composite patterned entity model using EF4 w/ the code-first CTP feature:
public abstract partial class CacheEntity
{
[Key]public string Hash { get; set; }
public string Creator { get; set; }
public int EntityType { get; set; }
public string Name { get; set; }
public string Predecessor { get; set; }
public DateTime DateTimeCreated { get; set; }
public virtual ICollection<CacheReference> References { get; set; }
}
public partial class CacheBlob : CacheEntity
{
public byte[] Content { get; set; }
}
public partial class CacheCollection : CacheEntity
{
public virtual ICollection<CacheEntity> Children { get; set; }
}
public class CacheReference
{
public string Hash { get; set; }
[Key]public string Reference { get; set; }
public virtual CacheEntity Entity { get; set; }
}
public class CacheEntities : DbContext
{
public DbSet<CacheEntity> Entities { get; set; }
public DbSet<CacheReference> References { get; set; }
}
Before I split out the primitive/collection derived classes it all worked nicely, but now I get this:
Unable to determine the principal end of the 'Cache.DataAccess.CacheEntity_References'
relationship. Multiple added entities may have the same primary key.
I figured that it may have been getting confused, so I thought I'd spell it out explicitly using the fluent interface, rather than the DataAnnotation attributes. Here's what I think defines the relationship properly:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CacheEntity>().HasKey(ce => ce.Hash);
modelBuilder.Entity<CacheEntity>().HasOptional(ce => ce.References).WithMany();
modelBuilder.Entity<CacheReference>().HasKey(ce => ce.Reference);
modelBuilder.Entity<CacheReference>().HasRequired(cr => cr.Entity).WithOptional();
}
But I must be wrong, because now I get this:
Entities in 'CacheEntities.CacheReferenceSet' participate in the
'CacheReference_Entity' relationship. 0 related 'Entity' were found. 1 'Entity' is expected.
Various other ways of using the fluent API yield different errors, but nothing succeeds, so I am beginning to wonder whether these need to be done differently when I am using inheritance.
Any clues, links, ideas, guidance would be very welcome.
using the MapHierarchy works for me:
protected override void OnModelCreating(ModelBuilder builder){
builder.Entity<CacheBlob>().HasKey(b=> b.Hash).MapHierarchy();
}
As an example.
Further reference : http://blogs.msdn.com/b/efdesign/archive/2009/10/12/code-only-further-enhancements.aspx