EF6与MVC5系列(4):在MVC应用程序中使用弹性连接和命令拦截
发布日期:2025-03-29 15:14:10 浏览次数:6 分类:精选文章

本文共 4106 字,大约阅读时间需要 13 分钟。

这节教程将引入Entity Framework 6(EF6)的两个重要特性:弹性连接和命令拦截。这对于部署在云环境中的网站至关重要。弹性连接允许EF在遇到暂态网络问题时自动重试,从而提高系统的稳定性。命令拦截则可以记录所有发送到数据库的SQL查询,方便后续的审查和修改。

启用弹性连接

在部署网站到云服务(如Windows Azure SQL Database)时,由于资源共享和限流限制,网络连接中间常会出现暂态错误。这时候,弹性连接特性能帮助EF自动重试连接,确保数据访问的连续性。EF6的弹性连接配置需要满足以下要求:

  • 区分暂态错误和永久性异常。
  • 定期重试连接。
  • 确定重试的最大次数。

这几项配置可以在任何支持EF6的环境中手动设置,而Windows Azure SQL Database已预先配置好了这些参数。


启用命令拦截

为了测试弹性连接是否正常工作,我们需要模拟和记录暂态误差。手动制造暂态错误并不容易,尤其是在本地开发环境中。这里可以利用EF6的命令拦截特性来记录和模拟错误。


无障碍性的日志记录

为了便于日后审查和分析,我们需要一个灵活的日志记录接口。遵循单一责任原则,编写接口而不是直接使用 System.Diagnostics.Trace。如果未来需要更改日志方式,接口可以轻松实现新的类。

  • 创建 ILogger 接口,并在 Logging 文件夹中实现它。
  • namespace ContosoUniversity.Logging{    public interface ILogger    {        void Information(string message);        void Information(string fmt, params object[] vars);        void Information(Exception exception, string fmt, params object[] vars);        void Warning(string message);        void Warning(string fmt, params object[] vars);        void Warning(Exception exception, string fmt, params object[] vars);        void Error(string message);        void Error(string fmt, params object[] vars);        void Error(Exception exception, string fmt, params object[] vars);        void TraceApi(string component, string method, TimeSpan timespan, string fmt, params object[] vars);    }}
    1. 实现 Logger 类,使用 System.Diagnostics 导出日志到输出窗口。
    2. using System;using System.Diagnostics;namespace ContosoUniversity.Logging{    public class Logger : ILogger    {        private readonly TraceListener _traceListener = new TraceListener();        // 其他方法...    }}

      创建拦截器类

      为了记录和模拟错误,创建拦截器类继承自 DbCommandInterceptor。在拦截器中可以看到所有发送到数据库的SQL查询,并根据需要处理或记录它们。

    3. 创建用于记录的拦截器类 SchoolInterceptorLogging
    4. using System.Diagnostics;namespace ContosoUniversity.DAL{    public class SchoolInterceptorLogging : DbCommandInterceptor    {        private readonly ILogger _logger = new Logger();        private readonly Stopwatch _stopwatch = new Stopwatch();        public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext context)        {            base.ScalarExecuting(command, context);            _stopwatch.Restart();        }        public override void ScalarExecuted(DbCommand command, DbCommandInterceptionContext context)        {            _stopwatch.Stop();            if (context.Exception != null)            {                _logger.Error(context.Exception, "执行命令时发生错误:{0}", command.CommandText);            }            else            {                _logger.TraceApi("SQL Database", "SchoolInterceptor.ScalarExecuted", _stopwatch.Elapsed, "Command:{0}", command.CommandText);            }            base.ScalarExecuted(command, context);        }        // 其他方法同上...    }}

      模拟暂态错误

      创建另一个拦截器 SchoolInterceptorTransientErrors,用于在特定情况下生成虚拟的SqlException。

      using System;using System.Linq;namespace ContosoUniversity.DAL{    public class SchoolInterceptorTransientErrors : DbCommandInterceptor    {        private readonly ILogger _logger = new Logger();        private int _counter = 0;        public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext context)        {            // 检查是否有需要触发的条件            if (command.Parameters[0].Value.ToString() == "%Throw%")            {                _counter++;                if (!_counter > 4 && !context.Exception)                {                    _logger.Information("返回暂态错误命令:{0}", command.CommandText);                    var exception = CreateDummySqlException();                    context.Exception = exception;                }            }        }        // 其他方法...    }}

      测试和部署

    5. 将拦截器注册到EF中:

      using ContosoUniversity.DAL;using System.Data.Entity.Infrastructure.Interception;protected void Application_Start(){    AreaRegistration.RegisterAllAreas();    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);    RouteConfig.RegisterRoutes(RouteTable.Routes);    BundleConfig.RegisterBundles(BundleTable.Bundles);    DbInterception.Add(new SchoolInterceptorTransientErrors());    DbInterception.Add(new SchoolInterceptorLogging());}
    6. 测试时,运行项目并通过搜索框输入特定值,观察输出窗口中的日志和异常信息。


    7. 通过以上配置,您可以全面了解和使用EF6的弹性连接和命令拦截特性,同时实现对数据库操作的透明记录和错误处理。

    上一篇:Effective C# 学习笔记(四十五)减少装箱拆箱行为
    下一篇:EF6.0中出现未找到具有固定名称“System.Data.SqlClient”的 ADO.NET提供程序的实体框架提供程序解决办法...

    发表评论

    最新留言

    第一次来,支持一个
    [***.219.124.196]2025年05月03日 13时41分32秒

    关于作者

        喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
    -- 愿君每日到此一游!

    推荐文章

    echarts 如何在一条柱形显示两个数字_干货 | 如何快速制作数据地图?让你的可视化逼格再高一级!... 2023-01-24
    eclipse设置utf8编码_记住没:永远不要在 MySQL 中使用 UTF8 2023-01-24
    eclipse里source的快捷方法_Eclipse快捷键/快捷操作汇总 2023-01-24
    elasticsearch 查询_Elasticsearch地理信息存储及查询之Geo_Point 2023-01-24
    embedding层_【预估排序】Embedding+MLP: 深度学习预估排序通用框架(一) 2023-01-24
    excel中最常用的30个函数_Excel玩转数据分析常用的43个函数! 2023-01-24
    flink sql设置并行度_Flink 参数配置和常见参数调优 2023-01-24
    go 字符串替换_Go 每日一库之 quicktemplate 2023-01-24
    hex editor neo下载_口袋妖怪爆焰黑手机版下载-口袋妖怪爆焰黑手游下载v4.3.0 安卓版... 2023-01-24
    hibernate mysql 关联查询_spring-boot hibernate 双向关联查询的坑 2023-01-24
    hive 建表_sqoop的使用之导入到hive和mysql 2023-01-24
    hp工作站z8装Linux,惠普Z8G4双路最小工作站 2023-01-24
    html上传图片直接保存到数据库中,Editor上传图片路径存入数据库中怎么弄? 2023-01-24
    html游戏玩不了,WinXP网页游戏玩不了怎么办有哪些解决方法 2023-01-24
    html转jsp_JSP详解 2023-01-24
    ICLOUD储存空间要升级吗_有人像我一样需要恢复苹果手机icloud空间ios备份时 微信卡住不动了吗(已解决)... 2023-01-24
    image unity 原始尺寸_Unity基础教程-对象管理(十一)——生命周期(Growth and Death)... 2023-01-24
    iphone打字怎么换行_手持iPhone?你可能并不知道的小技巧! 2023-01-24
    jaccard相似度_自然语言处理之文本相似度计算 2023-01-24
    java http delete_java积累---HttpDelete请求方式传递参数 2023-01-24