最近由於項目須要,研究了下EF的讀寫分離,因此作了一個demo進行測試,下面是項目的結構mysql
表現層viewweb
主要提供Web、WebApi等表現層的解決方案sql
公共層public數據庫
主要提供項目公共類庫,數據緩存基礎方法等緩存
實體層modelmvc
主要提供數據庫映射模型,還有就是DDD領域操做模型ide
數據層Db測試
主要封裝EF操做基礎類ui
數據服務層Servicespa
主要提供數據庫操做服務、緩存操做服務
數據接口服務層inface
主要提供數據庫操做服務接口、緩存操做服務接口
1.首先是多數據庫的支持,目前就支持mysql/sqlservice,若是須要添加更多的數據庫支持,只須要再數據庫操做類型上面添加便可
/// <summary> /// 數據庫類型 /// </summary> public enum DbContextType : byte { SqlService = 1, MySql = 2 }
分別對mysql/sqlservice的上下文操做進行封裝
/// <summary> /// MySql操做類 /// </summary> [DbConfigurationType(typeof(MySqlEFConfiguration))] public class MySqlContext : DbContext { public DbSet<Test> TestEntities { get; set; } /// <summary> /// 配置默認的字符串連接 /// </summary> public MySqlContext() : base("DefaultConnection") { } /// <summary> /// 自定義數據庫連接 /// </summary> /// <param name="connenction"></param> public MySqlContext(string connenction) : base(connenction) { } /// <summary> /// 實體對應規則的映射配置 /// </summary> /// <param name="modelBuilder"></param> protected override void OnModelCreating(DbModelBuilder modelBuilder) { } }
/// <summary> /// Sql數據庫操做類 /// </summary> public class SqlServiceContext : DbContext { /// <summary> /// 配置默認的字符串連接 /// </summary> public SqlServiceContext() { } /// <summary> /// 自定義數據庫連接 /// </summary> /// <param name="connenction"></param> public SqlServiceContext(string connenction) : base(connenction) { } /// <summary> /// 實體對應規則的映射配置 /// </summary> /// <param name="modelBuilder"></param> protected override void OnModelCreating(DbModelBuilder modelBuilder) { } }
在view調用時候,進行ef上下文初始化只須要設置類型
/// <summary> /// 數據庫策略初始化類 /// </summary> public static class DBInitializer { public static DbContextType DbContextType { get; set; } /// <summary> /// 數據庫初始化策略配置 /// </summary>` public static void Initialize(DbContextType ContextType) { string IsUsedWR = System.Configuration.ConfigurationManager.AppSettings["IsUsedWR"]; DbContextType = ContextType; ///得到數據庫最後一個版本 // Database.SetInitializer<DBContextHelper>(new MigrateDatabaseToLatestVersion<DBContextHelper, DBConfiguration>()); if (ContextType == DbContextType.SqlService) { Database.SetInitializer(new MigrateDatabaseToLatestVersion<WriteSqlServiceContext, WriteSqlServiceDBConfiguration>()); if (IsUsedWR == "1") { Database.SetInitializer(new MigrateDatabaseToLatestVersion<ReadSqlServiceContext, ReadSqlSqlServiceDBConfiguration>()); } else { Database.SetInitializer<ReadSqlServiceContext>(null); } } else { Database.SetInitializer(new MigrateDatabaseToLatestVersion<WriteMySqlContext, WriteMySqlDBConfiguration>()); if (IsUsedWR == "1") { Database.SetInitializer(new MigrateDatabaseToLatestVersion<ReadMySqlContext, ReadMySqlDBConfiguration>()); } else { Database.SetInitializer<ReadMySqlContext>(null); } //Database.SetInitializer<WriteMySqlContext>(null); // Database.SetInitializer<ReadMySqlContext>(null); } // Database.SetInitializer<DBContextHelper>(null); ///刪除原來數據庫 從新建立數據庫 //Database.SetInitializer(new DropCreateDatabaseIfModelChanges<ContextHelper>()); // Database.SetInitializer<ContextHelper>(new DropCreateDatabaseIfModelChanges<ContextHelper>()); } }
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); //Autofac //ContainerBuilder builder = new ContainerBuilder(); //builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()); //IContainer container = builder.Build(); //DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); //Autofac初始化過程 ContainerBuilder builder = new ContainerBuilder(); builder.RegisterControllers(System.Reflection.Assembly.GetExecutingAssembly());//註冊mvc容器的實現 var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList(); builder.RegisterAssemblyTypes(assemblys.ToArray()).Where(t => t.Name.Contains("Service")).AsImplementedInterfaces(); var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); //初始化數據庫 DBInitializer.Initialize(DbContextType.MySql); } }
經過上面多數據庫的支持已經完成,下面進行讀寫分離,分別進行繼承上述上下文操做
/// <summary> /// 讀 /// </summary> public class WriteSqlServiceContext : SqlServiceContext { public WriteSqlServiceContext() : base("") { } } /// <summary> /// 寫 /// </summary> public class ReadSqlServiceContext : SqlServiceContext { public ReadSqlServiceContext() : base("") { } }
經過工廠類進行初始化
/// <summary> /// 上下文工廠類 /// </summary> public static class Contextfactory { /// <summary> /// 獲取上下文 /// </summary> /// <returns></returns> public static DbContext GetContext(DbOpertionType OpertionType) { DbContextType ContextType = DBInitializer.DbContextType; if (ContextType == DbContextType.MySql) { if (OpertionType == DbOpertionType.Read) return new ReadMySqlContext(); else return new WriteMySqlContext(); } else { if (OpertionType == DbOpertionType.Read) return new ReadSqlServiceContext(); else return new WriteSqlServiceContext(); } } /// <summary> /// 獲取上下文操做 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="OpertionType"></param> /// <returns></returns> public static TEntity CallContext<TEntity>(DbOpertionType OpertionType) where TEntity: DbContext { var DbContext = GetContext(OpertionType); return (TEntity)DbContext; } }
最後配置webcofig便可
<!--數據庫配置(WriteMySqlConnection:讀數據庫,ReadMySqlConnection:寫數據庫 若是無須要進行 就配置IsUsedWR,2個連接都寫寫入庫)--> <connectionStrings> <add name="WriteMySqlConnection" connectionString="data source=*; Initial Catalog=YK_Test_WriteDB ; uid=root; pwd=yk12345;Charset=utf8" providerName="MySql.Data.MySqlClient" /> <add name="ReadMySqlConnection" connectionString="data source=*; Initial Catalog=YK_Test_ReadDB ; uid=root; pwd=yk12345;Charset=utf8" providerName="MySql.Data.MySqlClient" /> </connectionStrings> <!--數據庫讀取分離配置--> <!--是否開啓讀寫分離 1:開啓 0:不開啓--> <add key="IsUsedWR" value="1"/>
最後進行測試
public class TestController : Controller { private ITestService _TestServiceDb { get; set; } public TestController(ITestService TestServiceDb) { _TestServiceDb = TestServiceDb; } // GET: Test public ActionResult Index() { var result = _TestServiceDb.AddEntity(new Test() { ID=Guid.NewGuid(), Age=11, CreateTime=DateTime.Now, Name="Test" }); var NewResult = _TestServiceDb.GetEntityByID(result.ID); return View(); } }
搞定,可能在代碼上有點累贅,可是總算是可行的。
若是有興趣的朋友能夠留下郵箱,而後發全代碼一塊兒研究,謝謝!