Answered by:
Entity Framework 4.1x Code First

Question
-
Hi folks,Does anyone know whether it is possible to use more than one DbContext withinEntity Framework 4.1x using the Code First approach.The background of this question is that the project consists of a significant numberof classes within the model and in the next step to tables within a datastore. So, ifwe talk to separation of concerns splitting a large project into it's parts would be use-useful, right? DataBase.SetInitializer( new CreateDatabaseBlahBlahBlah<MyDbContext>() )won't be suitable here... Right too? Are you seriously using a DbContext with 100 IDbSetmembers? If so, good to know that that's the way to do....How do you manage bigger projects with a Code First approach and Entity Framework 4.x?Thank you in advance Günther,a convinced and passionated Microsofty!
qhautWednesday, November 2, 2011 4:57 PM
Answers
-
Hi,
yes this is possible. You are talking about "bigger projects". Then i think you should implement EF with Generic Repository, DatabaseFactory and UnitOfWork Pattern. I use this approach in my project and I could add several dbcontexts, but i dont need it, because its just a class with the DBSet Properties. Every Entity has a IRepository<DbSetType> that gets the DBContext (DatabaseFactory) injected by DI and fetches the dbset from the context property using DataContext.Set<TEntity>() method.
Here is another similiar discussion that should help you out.
http://stackoverflow.com/questions/6654355/multiple-dbcontexts-in-n-tier-application
HTH
Holger
- Marked as answer by Günther Schabus Sunday, November 6, 2011 12:21 PM
Wednesday, November 2, 2011 7:44 PM -
Hi,
for development cycles I use RecreateIfModelChanges initializer. This makes development really fast. Sure. This doent work anymore after you went productive. So i make changes manually with management studio / T-SQL and deploy the generated sql scripts. I will try EF migrations soon. For now the manual way is fine for my purposes.
http://blogs.msdn.com/b/adonet/archive/2011/09/21/code-first-migrations-alpha-3-no-magic-walkthrough.aspx
http://blogs.msdn.com/b/adonet/archive/2011/09/21/code-first-migrations-alpha-3-with-magic-walkthrough-automatic-migrations.aspxGreets,
Holger
- Marked as answer by Günther Schabus Sunday, November 6, 2011 12:21 PM
Sunday, November 6, 2011 11:35 AM -
Hi,
i try to give an example. One thing I have forgotten. If you are using DropCreateDatabaseIfModelChanges you cant use the same database, because booth DbContexts would use the same EdmMetadata.
If you want to split your context and use DropCreateDatabaseIfModelChanges you must use different databases.
Here is an example console app, that uses two databases, two contexts. The only thing to remind is to call Database.Initialize for all of your DbContexts, because SetInitializer would be overwritten..
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Entity; namespace MultipleDbContexts { using System.Data.Entity; public class User { public int Id { get; set; } public string Name { get; set; } } public class Log { public int Id { get; set; } public string Entry { get; set; } } public class UserContext : DbContext { public DbSet<User> Users { get; set; } } public class LogContext : DbContext { public DbSet<Log> Logs { get; set; } } public class UserContextInitalizer : DropCreateDatabaseIfModelChanges<UserContext> { protected override void Seed(UserContext context) { Console.WriteLine("UserContext seeding.."); /*custom init stuff goes here*/ context.Users.Add(new User() { Name = "Holger" }); context.Users.Add(new User() { Name = "Günther" }); } } public class LogContextInitalizer : DropCreateDatabaseIfModelChanges<LogContext> { protected override void Seed(LogContext context) { Console.WriteLine("LogContext seeding.."); /*custom init stuff goes here*/ context.Logs.Add(new Log() { Entry = "Testentry 1." }); context.Logs.Add(new Log() { Entry = "Testentry 2." }); } } class Program { static void Main(string[] args) { Database.SetInitializer(new LogContextInitalizer()); //run initialize manually, because we have multiple dbContexts using (var context = new LogContext()) { context.Database.Initialize(false); } Database.SetInitializer(new UserContextInitalizer()); //run initialize manually, because we have multiple dbContexts using (var context = new UserContext()) { context.Database.Initialize(false); } using(var context = new LogContext()) { foreach(var user in context.Logs) Console.WriteLine(user.Id + ": " + user.Entry); } using (var context = new UserContext()) { foreach (var user in context.Users) Console.WriteLine(user.Id + ": " + user.Name); } Console.Read(); } } }
The output for the first run (or the run after you changed the model) would be:UserContext seeding..
LogContext seeding..
1: Testentry 1.
2: Testentry 2.
1: Holger
2: Günther
If you run it again, without changing the entity model:1: Testentry 1.
2: Testentry 2.
1: Holger
2: GüntherHTH
Holger
PS: app.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="UserContext"
connectionString="data source=localhost;initial catalog=TestUserDb;Integrated Security=SSPI"
providerName="System.Data.SqlClient" /> <add name="LogContext"
connectionString="data source=localhost;initial catalog=TestLogDb;Integrated Security=SSPI"
providerName="System.Data.SqlClient" /> </connectionStrings> </configuration>
- Edited by Holger Kreissl Sunday, November 6, 2011 7:50 PM c&p fail
- Marked as answer by Günther Schabus Thursday, December 1, 2011 12:16 PM
Sunday, November 6, 2011 2:19 PM
All replies
-
Hi,
yes this is possible. You are talking about "bigger projects". Then i think you should implement EF with Generic Repository, DatabaseFactory and UnitOfWork Pattern. I use this approach in my project and I could add several dbcontexts, but i dont need it, because its just a class with the DBSet Properties. Every Entity has a IRepository<DbSetType> that gets the DBContext (DatabaseFactory) injected by DI and fetches the dbset from the context property using DataContext.Set<TEntity>() method.
Here is another similiar discussion that should help you out.
http://stackoverflow.com/questions/6654355/multiple-dbcontexts-in-n-tier-application
HTH
Holger
- Marked as answer by Günther Schabus Sunday, November 6, 2011 12:21 PM
Wednesday, November 2, 2011 7:44 PM -
Hi Holger,Yes, I see your point. Thanks for clarification. There is one question left. What's yourfavorite way to hold your database and your model in sync? Are you using Database.SetInitializer( new Create...<YourDbContext>() )(which works with one DbContext only) or are you following a different approach?Thanks for your answer and have a great day!hand, günther
Günther SchabusSunday, November 6, 2011 10:20 AM -
Hi,
for development cycles I use RecreateIfModelChanges initializer. This makes development really fast. Sure. This doent work anymore after you went productive. So i make changes manually with management studio / T-SQL and deploy the generated sql scripts. I will try EF migrations soon. For now the manual way is fine for my purposes.
http://blogs.msdn.com/b/adonet/archive/2011/09/21/code-first-migrations-alpha-3-no-magic-walkthrough.aspx
http://blogs.msdn.com/b/adonet/archive/2011/09/21/code-first-migrations-alpha-3-with-magic-walkthrough-automatic-migrations.aspxGreets,
Holger
- Marked as answer by Günther Schabus Sunday, November 6, 2011 12:21 PM
Sunday, November 6, 2011 11:35 AM -
Hi Holger,
Thanks again for your help. How and when do you operatively call your Database.SetInitializer with
the mentioned RecreateIfModelChanges - Strategy? By supporting more than one DbContext Instances -
each with a different subset of the model (UnitOfWork) - how do you manage that? I ran out of ideas
using different DbContext Implementations (AuthorizationContext, CustomerContext and so on....) with
this Database.SetInitializer( Strategy<DbContext> ) approach.
Probably I am completely wrong here. Can you provide me with one line of code how do you handle
multiple DbContext Implementations and the database update cycles.Thank you holger!
laugh @ your problems. everybody else does.Sunday, November 6, 2011 12:13 PM -
Hi,
i try to give an example. One thing I have forgotten. If you are using DropCreateDatabaseIfModelChanges you cant use the same database, because booth DbContexts would use the same EdmMetadata.
If you want to split your context and use DropCreateDatabaseIfModelChanges you must use different databases.
Here is an example console app, that uses two databases, two contexts. The only thing to remind is to call Database.Initialize for all of your DbContexts, because SetInitializer would be overwritten..
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Entity; namespace MultipleDbContexts { using System.Data.Entity; public class User { public int Id { get; set; } public string Name { get; set; } } public class Log { public int Id { get; set; } public string Entry { get; set; } } public class UserContext : DbContext { public DbSet<User> Users { get; set; } } public class LogContext : DbContext { public DbSet<Log> Logs { get; set; } } public class UserContextInitalizer : DropCreateDatabaseIfModelChanges<UserContext> { protected override void Seed(UserContext context) { Console.WriteLine("UserContext seeding.."); /*custom init stuff goes here*/ context.Users.Add(new User() { Name = "Holger" }); context.Users.Add(new User() { Name = "Günther" }); } } public class LogContextInitalizer : DropCreateDatabaseIfModelChanges<LogContext> { protected override void Seed(LogContext context) { Console.WriteLine("LogContext seeding.."); /*custom init stuff goes here*/ context.Logs.Add(new Log() { Entry = "Testentry 1." }); context.Logs.Add(new Log() { Entry = "Testentry 2." }); } } class Program { static void Main(string[] args) { Database.SetInitializer(new LogContextInitalizer()); //run initialize manually, because we have multiple dbContexts using (var context = new LogContext()) { context.Database.Initialize(false); } Database.SetInitializer(new UserContextInitalizer()); //run initialize manually, because we have multiple dbContexts using (var context = new UserContext()) { context.Database.Initialize(false); } using(var context = new LogContext()) { foreach(var user in context.Logs) Console.WriteLine(user.Id + ": " + user.Entry); } using (var context = new UserContext()) { foreach (var user in context.Users) Console.WriteLine(user.Id + ": " + user.Name); } Console.Read(); } } }
The output for the first run (or the run after you changed the model) would be:UserContext seeding..
LogContext seeding..
1: Testentry 1.
2: Testentry 2.
1: Holger
2: Günther
If you run it again, without changing the entity model:1: Testentry 1.
2: Testentry 2.
1: Holger
2: GüntherHTH
Holger
PS: app.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="UserContext"
connectionString="data source=localhost;initial catalog=TestUserDb;Integrated Security=SSPI"
providerName="System.Data.SqlClient" /> <add name="LogContext"
connectionString="data source=localhost;initial catalog=TestLogDb;Integrated Security=SSPI"
providerName="System.Data.SqlClient" /> </connectionStrings> </configuration>
- Edited by Holger Kreissl Sunday, November 6, 2011 7:50 PM c&p fail
- Marked as answer by Günther Schabus Thursday, December 1, 2011 12:16 PM
Sunday, November 6, 2011 2:19 PM -
Holger,
I am truly sorry for not replying to your answer! I thought I did!
Anyway, thank you for your efford and I reached my goal. The point
is, that it is not possible to split DbContext-Classes within the same
datastore.
Following the spirit of Units of Work it's hard to maintains 100 IDbSet<TableXYZ>
within one single DbContext. Anyway, not a big deal right now.Thank you, Günther
laugh @ your problems. everybody else does.Thursday, December 1, 2011 12:16 PM -
yw.. thanks for the feedback :)
Greetings
Holger
Thursday, December 1, 2011 12:41 PM