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/change-entity-framework-storage-db-schema-in-runtime.aspx?CommentPosted=true#commentmessage
This works perfectly, but only for queries, not for modifications.
Any idea why?
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. Next create the function that will modify your store schema . ssdl file in memory.
You must own the schema to use ALTER SCHEMA . To rename a schema you must also have the CREATE privilege for the database. To alter the owner, you must also be a direct or indirect member of the new owning role, and you must have the CREATE privilege for the database.
When a schema is changed, it creates a ripple through all the applications that depend on that schema. With relational databases, a schema change can take weeks for developers to deal with while they adapt their code to the new model.
Well, I was looking for this piece of code all around the Internet. In the end I had to do it myself. It's based on Brandon Haynes adapter, but this function is all you need to change the schema on runtime - and you don't need to replace the autogenerated context constructors.
public static EntityConnection Create( string schema, string connString, string model) { XmlReader[] conceptualReader = new XmlReader[] { XmlReader.Create( Assembly .GetExecutingAssembly() .GetManifestResourceStream(model + ".csdl") ) }; XmlReader[] mappingReader = new XmlReader[] { XmlReader.Create( Assembly .GetExecutingAssembly() .GetManifestResourceStream(model + ".msl") ) }; var storageReader = XmlReader.Create( Assembly .GetExecutingAssembly() .GetManifestResourceStream(model + ".ssdl") ); XNamespace storageNS = "http://schemas.microsoft.com/ado/2009/02/edm/ssdl"; var storageXml = XElement.Load(storageReader); foreach (var entitySet in storageXml.Descendants(storageNS + "EntitySet")) { var schemaAttribute = entitySet.Attributes("Schema").FirstOrDefault(); if (schemaAttribute != null) { schemaAttribute.SetValue(schema); } } storageXml.CreateReader(); StoreItemCollection storageCollection = new StoreItemCollection( new XmlReader[] { storageXml.CreateReader() } ); EdmItemCollection conceptualCollection = new EdmItemCollection(conceptualReader); StorageMappingItemCollection mappingCollection = new StorageMappingItemCollection( conceptualCollection, storageCollection, mappingReader ); var workspace = new MetadataWorkspace(); workspace.RegisterItemCollection(conceptualCollection); workspace.RegisterItemCollection(storageCollection); workspace.RegisterItemCollection(mappingCollection); var connectionData = new EntityConnectionStringBuilder(connString); var connection = DbProviderFactories .GetFactory(connectionData.Provider) .CreateConnection(); connection.ConnectionString = connectionData.ProviderConnectionString; return new EntityConnection(workspace, connection); }
The resulting EntityConnection should be passed as a parameter when instantiating the context. You can modify it, so all ssdl models are modified by this function, not only the specified one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With