• EF6 Database First (DbContext)


    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:

    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

  • 相关阅读:
    【高并发】面试官问我:为什么局部变量是线程安全的?
    Java中的String到底占用多大的内存空间?你所了解的可能都是错误的!!
    【高并发】学好并发编程,关键是要理解这三个核心问题
    【高并发】高并发分布式锁架构解密,不是所有的锁都是分布式锁!!
    12张图带你彻底理解分布式事务产生的场景和解决方案!!
    【高并发】面试官:讲讲高并发场景下如何优化加锁方式?
    【高并发】秒杀系统架构解密,不是所有的秒杀都是秒杀(升级版)!!
    十一长假我肝了这本超硬核PDF,现决定开源!!
    一文搞懂PV、UV、VV、IP及其关系与计算
    我把这个贼好用的Excel导出工具开源了!!
  • 原文地址:https://www.cnblogs.com/jimcsharp/p/6024082.html
Copyright © 2020-2023  润新知