I have two customer database tables, but want to use the same model and context, just be able to determine at runtime if i want to load from the live or the prospect customer table. The problem is that a context OnModelCreating runs only once by default, so you can’t leave parameters there to switch for you. One solution was to copy the context, but I found I needed a bit too much extra code in the usage to determine which to use. To understand a solution it is worth using the Visual Studio Object Browser DbContext remarks. “The protected OnModelCreating method can be overridden to tweak this model. More control over the model used for the Model First approach can be obtained by creating a System.Data.Entity.Infrastructure.DbCompiledModel explicitly from a System.Data.Entity.DbModelBuilder and passing this model to one of the DbContext constructors.” So you can create a DbCompliedModel (System.Data.Entity.Infrastructure) and store it if you may switch back to it, then use it to create an instance of your context. This can be done on the context using Shared / Static factory method.
Public Class CustomerContext
Inherits DbContext
Property Customers() As DbSet(Of Customer)
Private Shared dbCompiledModelLive As DbCompiledModel
Private Shared dbCompiledModelProspect As DbCompiledModel
Private Sub New(connection As DbConnection, model As DbCompiledModel)
MyBase.New(connection, model, True)
End Sub
Shared Function CreateCustomerContext(LiveCustomer As Boolean) As CustomerContext
Dim conStr = ConfigurationManager.ConnectionStrings("BusinessEntities").ConnectionString
Dim DbConnection As New SqlConnection(conStr)
If LiveCustomer Then
If dbCompiledModelLive IsNot Nothing Then
Return New CustomerContext(DbConnection, dbCompiledModelLive)
End If
Else
If dbCompiledModelProspect IsNot Nothing Then
Return New CustomerContext(DbConnection, dbCompiledModelProspect)
End If
End If
Dim modelBuilder As New DbModelBuilder
CustomerMap.LiveCustomerFlag1 = LiveCustomer
modelBuilder.Configurations.Add(New CustomerMap)
Dim model = modelBuilder.Build(DbConnection)
If LiveCustomer Then
dbCompiledModelLive = model.Compile
Return New CustomerContext(DbConnection, dbCompiledModelLive)
End If
dbCompiledModelProspect = model.Compile
Return New CustomerContext(DbConnection, dbCompiledModelProspect)
End Function
End Class
This all works
<TestMethod()> _
Public Sub CustomersTest()
Dim targetLive = CustomerContext.CreateCustomerContext(True)
Dim actual As DbSet(Of Customer) = targetLive.Customers
Debug.Print("Live Customers")
PrintResult(actual)
Assert.IsTrue(actual.Count > 2)
Dim targetProspect = CustomerContext.CreateCustomerContext(False)
actual = targetProspect.Customers
Debug.Print("")
Debug.Print("Prospect Customers")
PrintResult(actual)
Assert.AreEqual(0, actual.Count)
actual = targetLive.Customers
Debug.Print("")
Debug.Print("Live Customers")
PrintResult(actual)
Assert.IsTrue(actual.Count > 2)
targetLive = CustomerContext.CreateCustomerContext(True)
actual = targetLive.Customers
Debug.Print("")
Debug.Print("Live Customers")
PrintResult(actual)
Assert.IsTrue(actual.Count > 2)
End Sub
Private Sub PrintResult(actual As DbSet(Of Customer))
For Each item As Customer In actual
Debug.Print(String.Concat(item.ID, vbTab, item.Customer1))
Next
End Sub
Could be useful With thanks also to: http://romiller.com/2011/05/23/ef-4-1-multi-tenant-with-code-first/