Changing schema name on runtime - Entity Framework

前端 未结 6 648
梦谈多话
梦谈多话 2020-12-01 04:12

I need to change the storage schema of the entities on runtime. I\'ve followed a wonderful post, available here: http://blogs.microsoft.co.il/blogs/idof/archive/2008/08/22/c

6条回答
  •  自闭症患者
    2020-12-01 04:18

    I was able to convert the solution from Jan Matousek to work in vb.net 2013 with entity framework 6. I will also try to explain how to use the code in vb.net.

    We have a JD Edwards Database which uses different Schema's for each environment (TESTDTA, CRPDTA, PRODDTA). This makes switching between environments cumbersome as you have to manually modify the .edmx file if you want to change environments.

    First step is to create a partial class that allows you to pass a value to the constructor of your entities, by default it uses the values from your config file.

    Partial Public Class JDE_Entities
        Public Sub New(ByVal myObjectContext As ObjectContext)
            MyBase.New(myObjectContext, True)
        End Sub
    End Class
    

    Next create the function that will modify your store schema .ssdl file in memory.

     Public Function CreateObjectContext(ByVal schema As String, ByVal connString As String, ByVal model As String) As ObjectContext
    
        Dim myEntityConnection As EntityConnection = Nothing
    
        Try
    
            Dim conceptualReader As XmlReader = XmlReader.Create(Me.GetType().Assembly.GetManifestResourceStream(model + ".csdl"))
            Dim mappingReader As XmlReader = XmlReader.Create(Me.GetType().Assembly.GetManifestResourceStream(model + ".msl"))
            Dim storageReader As XmlReader = XmlReader.Create(Me.GetType().Assembly.GetManifestResourceStream(model + ".ssdl"))
    
            Dim storageNS As XNamespace = "http://schemas.microsoft.com/ado/2009/11/edm/ssdl"
    
            Dim storageXml = XDocument.Load(storageReader)
            Dim conceptualXml = XDocument.Load(conceptualReader)
            Dim mappingXml = XDocument.Load(mappingReader)
    
            For Each myItem As XElement In storageXml.Descendants(storageNS + "EntitySet")
                Dim schemaAttribute = myItem.Attributes("Schema").FirstOrDefault
    
                If schemaAttribute IsNot Nothing Then
                    schemaAttribute.SetValue(schema)
                End If
    
            Next
    
            storageXml.Save("storage.ssdl")
            conceptualXml.Save("storage.csdl")
            mappingXml.Save("storage.msl")
    
            Dim storageCollection As StoreItemCollection = New StoreItemCollection("storage.ssdl")
            Dim conceptualCollection As EdmItemCollection = New EdmItemCollection("storage.csdl")
    
            Dim mappingCollection As StorageMappingItemCollection = New StorageMappingItemCollection(conceptualCollection, storageCollection, "storage.msl")
    
    
            Dim workspace = New MetadataWorkspace()
            workspace.RegisterItemCollection(conceptualCollection)
            workspace.RegisterItemCollection(storageCollection)
            workspace.RegisterItemCollection(mappingCollection)
    
            Dim connectionData = New EntityConnectionStringBuilder(connString)
            Dim connection = DbProviderFactories.GetFactory(connectionData.Provider).CreateConnection()
    
            connection.ConnectionString = connectionData.ProviderConnectionString
    
            myEntityConnection = New EntityConnection(workspace, connection)
    
            Return New ObjectContext(myEntityConnection)
    
        Catch ex As Exception
    
        End Try
    
    End Function
    

    Make sure that the storageNS namespace hardcoded value matches the one used in your code, you can view this by debugging the code and examining the storageXML variable to see what was actually used.

    Now you can pass a new schema name, and different database connection info at runtime when you create your entities. No more manual .edmx changes required.

    Using Context As New JDE_Entities(CreateObjectContext("NewSchemaNameHere", ConnectionString_EntityFramework("ServerName", "DatabaseName", "UserName", "Password"), "JDE_Model"))
    
                Dim myWO = From a In Context.F4801 Where a.WADOCO = 400100
    
                If myWO IsNot Nothing Then
                    For Each r In myWO
                        Me.Label1.Text = r.WADL01
                    Next
                End If
            End Using
    

    These were the .net libraries used:

    Imports System.Data.Entity.Core.EntityClient
    Imports System.Xml
    Imports System.Data.Common
    Imports System.Data.Entity.Core.Metadata.Edm
    Imports System.Reflection
    Imports System.Data.Entity.Core.Mapping
    Imports System.Data.Entity.Core.Objects
    Imports System.Data.Linq
    Imports System.Xml.Linq
    

    Hope that helps anyone out there with the same issues.

提交回复
热议问题