EF架构~通过EF6的DbCommand拦截器来实现数据库读写分离
前几天看了一个基于sqlserver的负载均衡与读写分离的软件Moebius,实现的方式还是不错的,这使得用sqlserver数据库的同学时有机会对数据库进行更有效的优化了
看着人有做的东西,自己也想用EF来实现一个读写分离,所以就有了本篇文章,仓储大叔读写分离的思路是:
1 用sqlserver自带的发布、订阅实现主,从数据库的结构,同步这事由sql帮我们完成
2 配置文件建立几个供只读的数据库连接串
3 建立SQL命令拦截器
4 修改大叔的DbContextRepository基数,添加拦截行为
5 测试,搞定
有了上面的想法,咱就可以干事了,第一步不用说了,可以自己百度,从第2步说起
2 配置文件建立几个供只读的数据库连接串
<!-- 只写--> <add name="backgroundEntities" connectionString="metadata=res://*/background.csdl|res://*/background.ssdl|res://*/background.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=background;persist security info=True;user id=sa;password=zzl123;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" /> <!-- 只读--> <add name="backgroundEntitiesRead" connectionString="metadata=res://*/background.csdl|res://*/background.ssdl|res://*/background.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=background_Read1;persist security info=True;user id=sa;password=zzl123;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
3 建立SQL命令拦截器
/// <summary> /// SQL命令拦截器 /// </summary> public class NoLockInterceptor : DbCommandInterceptor { private static readonly Regex _tableAliasRegex = new Regex(@"(?<tableAlias>AS \[Extent\d+\](?! WITH \(NOLOCK\)))", RegexOptions.Multiline | RegexOptions.IgnoreCase); [ThreadStatic] public static bool SuppressNoLock; public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { string conn = command.Connection.ConnectionString; base.NonQueryExecuting(command, interceptionContext); } public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { command.Connection.Close(); command.Connection.ConnectionString = "data source=.;initial catalog=background_Read1;persist security info=True;user id=sa;password=zzl123;multipleactiveresultsets=True;application name=EntityFramework"; command.Connection.Open(); if (!SuppressNoLock) { command.CommandText = _tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)"); } } public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { command.Connection.Close(); command.Connection.ConnectionString = "data source=.;initial catalog=background_Read1;persist security info=True;user id=sa;password=zzl123;multipleactiveresultsets=True;application name=EntityFramework"; command.Connection.Open(); if (!SuppressNoLock) { command.CommandText = _tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)"); } } }
4 修改大叔的DbContextRepository基数,添加拦截行为
public DbContextRepository(IUnitOfWork db, Action<string> logger) { UnitWork = db; Db = (DbContext)db; Logger = logger; ((IObjectContextAdapter)Db).ObjectContext.CommandTimeout = 0; //SQL语句拦截器 System.Data.Entity.Infrastructure.Interception.DbInterception.Add(new EntityFrameworks.Data.Core.Common.NoLockInterceptor()); EntityFrameworks.Data.Core.Common.NoLockInterceptor.SuppressNoLock = true; }
5 大功造成,感谢阅读!
本文章代码没有全部展示,只是展示一种思想,希望可以给大家带来帮助。
分类:
其它 / 系统架构
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
2012-01-07 LINQ TO SQL中还是用传统的连接串方式建立DbContext更好些