EF6 Database First (DbContext) - Change Schema at runtime
2016-11-02 19:05
411 查看
Problem:
There are two SQL databases (dev and live) with on Azure
which has identical table structures but different table schema name. We
need a way to change the schema name at runtime thus we can maintain
one code base for the two database
Solution:
then can use the entity like below with the DBHelper
Note: if you use different EF version, you may need to change the csdl or ssdl namespace in above code
Reference:
http://blogs.msdn.com/b/dbrowne/archive/2013/08/30/entity-framework-schema-redirection.aspx http://pastebin.com/UpqUzezq
There are two SQL databases (dev and live) with on Azure
which has identical table structures but different table schema name. We
need a way to change the schema name at runtime thus we can maintain
one code base for the two database
Solution:
public class DBHelper { public static MyDBEntities Connect() { if (ConfigurationManager.ConnectionStrings["DBConnection"] == null) { throw new ApplicationException("connectionStrings in .config file is missing a connection named 'connectionStrings'"); } string connectionString = ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString; //parse schema name from database name SqlConnection conn = new SqlConnection(connectionString); string schema = conn.Database.Replace("_db", ""); return Connect<MyDBEntities>(connectionString, schema); } private static T Connect<T>(string connectionString, string schema) where T : DbContext { var assembly = typeof(T).Assembly; var type = typeof(T); var resourceNames = assembly.GetManifestResourceNames(); string contextName = null; // code used to avoid of getting the wrong csdl, used when you have more than one // DbContext on your project foreach (var csdl in resourceNames.Where(r => r.EndsWith(".csdl"))) { var csdlDocument = XDocument.Load(assembly.GetManifestResourceStream(csdl)); XNamespace csdlNamespace = "http://schemas.microsoft.com/ado/2009/11/edm"; var name = csdlDocument.Root.Elements(csdlNamespace + "EntityContainer").First().Attribute("Name").Value; if (type.Name.Equals(name)) { contextName = csdl.Replace(".csdl", ""); break; } } string csdlName = resourceNames.Single(r => r.Equals(contextName + ".csdl")); string ssdlName = resourceNames.Single(r => r.Equals(contextName + ".ssdl")); string mslName = resourceNames.Single(r => r.Equals(contextName + ".msl")); var ssdlDocument = XDocument.Load(assembly.GetManifestResourceStream(ssdlName)); XNamespace ssdlNamespace = "http://schemas.microsoft.com/ado/2009/11/edm/ssdl"; var functions = ssdlDocument.Root.Elements(ssdlNamespace + "Function").ToList(); foreach (var f in functions) f.SetAttributeValue("Schema", schema); var entitySets = ssdlDocument.Root.Elements(ssdlNamespace + "EntityContainer").ToList().Elements(ssdlNamespace + "EntitySet").ToList(); foreach (var es in entitySets) if (es.Attribute("Schema") != null) es.SetAttributeValue("Schema", schema); Func<string, XmlReader[]> getFromResource = (name) => { using (var s = assembly.GetManifestResourceStream(name)) { return new XmlReader[] { XDocument.Load(s).CreateReader() }; } }; var storeItems = new StoreItemCollection(new XmlReader[] { ssdlDocument.CreateReader() }); var edmItems = new EdmItemCollection(getFromResource(csdlName)); var mappingItems = new StorageMappingItemCollection(edmItems, storeItems, getFromResource(mslName)); var workspace = new MetadataWorkspace(); workspace.RegisterItemCollection(storeItems); workspace.RegisterItemCollection(edmItems); workspace.RegisterItemCollection(mappingItems); workspace.RegisterItemCollection(new ObjectItemCollection()); workspace.LoadFromAssembly(assembly); var storeConn = new SqlConnection(connectionString); ConstructorInfo contextConstructor = typeof(T).GetConstructor(new Type[] { typeof(DbConnection)}); //require a partial class of the EF model to accept one parameter of type DbConnection var entityConn = new EntityConnection(workspace, storeConn); return (T)contextConstructor.Invoke(new Object[] { entityConn }); } } public partial class MyDBEntities { public MyDBEntities(DbConnection existingConnection):base(existingConnection,true) { } }
then can use the entity like below with the DBHelper
using (var db = DBHelper.Connect()) { //you code here to use db }
Note: if you use different EF version, you may need to change the csdl or ssdl namespace in above code
Reference:
http://blogs.msdn.com/b/dbrowne/archive/2013/08/30/entity-framework-schema-redirection.aspx http://pastebin.com/UpqUzezq
相关文章推荐
- EF6 Database First (DbContext) - Change Schema at runtime
- 浅谈EF框架(二)--DataBaseFirst
- EF三种编程方式详细图文教程(C#+EF)之Database First
- Code First 与 DataBase First(.edmx)的区别以及 对于EF对非 ms-sql server数据库的支持
- EF DataBase First生成model的验证
- EF和MVC系列文章导航:EF Code First、DbContext、MVC
- EF 4.1 Model & Database First Walkthrough 学习摘要
- Exception in thread "main" java.lang.RuntimeException: Hive metastore database is not initialized. Please use schematool (e.g. ./schematool -initSchema -dbType ...) to create the schema. If needed, do
- EF三种编程方式详细图文教程(C#+EF)之Database First
- 【翻译】EF 4.2 Model & Database First演示
- 使用EF DataBaseFirst做一个简单的MVC3报名网站
- EF和MVC系列文章导航:EF Code First、DbContext、MVC
- EF DataBase First生成model的验证
- EF映射之DataBaseFirst
- Mysql EF Database First 生成标准C#规范的类文件结构
- EF DataBase First 动态拼接数据库连接
- How to Change .NET Configuration Files at Runtime (including for WCF)
- EF框架step by step(1)—Database-First
- 【ITOO高校云平台】——EF框架:DatabaseFirst
- EF之Database First数据库优先