本章原文地址:Connection Resiliency and Command Interception

原文有些地方讲的比较细,个人根据实际理解做些缩减,或者加入一些个人理解;

第1部分 弹性连接

为什么要弹性连接?什么是弹性连接?

在实际的网络应用中,尤其是在Internet上的网络应用,就算Web服务器和数据库服务器在一个数据中心,也不能保证WEB服务器和数据库服务器没有任何延迟或者其他网络问题;

尤其如PaaS层的Azure的SQL或者阿里的SQL、MySQL数据库服务器,都是做了网络负载均衡的,在一定的条件下能提供的服务是有限的,在其SLA里都会有定义;

而超出其SLA的部分请求就会被取消响应,那么在WEB网页应用设计的时候,就需要考虑这一点,在出现一些异常情况的时候,需要能够在短时间内进行一次或多次Retry.

这就称为:弹性的连接

原文中对EF6实现弹性连接功能仅做了简单代码就实现了,至于具体在实际项目中是不是就这么简单,本人还需要进一步深入学习。

先看看原文如何做的:

在DAL文件夹定义 SchoolConfiguration类,继承自DbConfiguration类, 在这个类中设置SQL数据库的执行策略 (execution strategy ,这个名词是EF6 对于Retry Policy 的命名

using System.Data.Entity;
using System.Data.Entity.SqlServer; namespace EFTest.DAL
{
public class SchoolConfiguration : DbConfiguration
{
public SchoolConfiguration()
{
SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
}
}
}

EF6会自动运行继承自DbConfiguration类的代码;当然也可以通过配置Web.config 来实现,可以参考 EntityFramework Code-Based Configuration
然后在 Student 控制器里增加申明:

using System.Data.Entity.Infrastructure;

最后就是将所有 Try-catch代码块的 catch 后面捕获的 Exception 类型转为 RetryLimitExceededException

catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}

这样就会是出现数据库连接异常的时候,进行Retry,多次Retry达到Limit值还是错误,则抛出异常。

更多的说明,需要参考: Entity Framework Connection Resiliency / Retry Logic

第2部分 命令拦截调试

设置好了弹性连接后,如何能够看到到底是不是Retry了,则需要一些调试手段;

当然你可以使用Web请求Log等来查看,或者EF6 提供的Dedicated Logging API (dedicated logging API)

本次直接采用EF6的 Interception 功能来实现。

对于日志记录来说,最好的方式是做一个接口来定义,而不是直接每次用硬代码来Call System.Diagnostics.Trace

因为这样,对于以后如果日志记录机制有调整的话,就容易很多了。

实际操作体验:

1、新建一个Logging 的文件夹

2、在文件夹中新建一个ILogger 接口,接口中定义了不同等级的信息处理方式;

TraceApi 可以跟踪连接外部服务例如SQL服务的每一步延迟情况;

using System;

namespace EFTest.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 componentName, string method, TimeSpan timespan);
void TraceApi(string componentName, string method, TimeSpan timespan, string properties);
void TraceApi(string componentName, string method, TimeSpan timespan, string fmt, params object[] vars);
}
}

3、在文件夹内新建Logger这个类,集成自ILogger接口,并实现接口内方法;

using System;
using System.Diagnostics;
using System.Text; namespace EFTest.Logging
{
public class Logger : ILogger
{
public void Information(string message)
{
Trace.TraceInformation(message);
} public void Information(string fmt, params object[] vars)
{
Trace.TraceInformation(fmt, vars);
} public void Information(Exception exception, string fmt, params object[] vars)
{
Trace.TraceInformation(FormatExceptionMessage(exception, fmt, vars));
} public void Warning(string message)
{
Trace.TraceWarning(message);
} public void Warning(string fmt, params object[] vars)
{
Trace.TraceWarning(fmt, vars);
} public void Warning(Exception exception, string fmt, params object[] vars)
{
Trace.TraceWarning(FormatExceptionMessage(exception, fmt, vars));
} public void Error(string message)
{
Trace.TraceError(message);
} public void Error(string fmt, params object[] vars)
{
Trace.TraceError(fmt, vars);
} public void Error(Exception exception, string fmt, params object[] vars)
{
Trace.TraceError(FormatExceptionMessage(exception, fmt, vars));
} public void TraceApi(string componentName, string method, TimeSpan timespan)
{
TraceApi(componentName, method, timespan, "");
} public void TraceApi(string componentName, string method, TimeSpan timespan, string fmt, params object[] vars)
{
TraceApi(componentName, method, timespan, string.Format(fmt, vars));
}
public void TraceApi(string componentName, string method, TimeSpan timespan, string properties)
{
string message = String.Concat("Component:", componentName, ";Method:", method, ";Timespan:", timespan.ToString(), ";Properties:", properties);
Trace.TraceInformation(message);
} private static string FormatExceptionMessage(Exception exception, string fmt, object[] vars)
{
// Simple exception formatting: for a more comprehensive version see
// http://code.msdn.microsoft.com/windowsazure/Fix-It-app-for-Building-cdd80df4
var sb = new StringBuilder();
sb.Append(string.Format(fmt, vars));
sb.Append(" Exception: ");
sb.Append(exception.ToString());
return sb.ToString();
}
}
}

看代码可以知道,实际是通过.NET 的 System.Diagnostics 来跟踪记录日志的;日志信息可以写到很多其他位置,例如Azure 的blob storage ;

本次,只是把日志输出到VS 的Output窗口;

在实际项目中,如果用其他记录日志机制来代替 System.Diagnostics的话,ILogging接口方式比较容易来实现这个切换。

下一步需要建一个拦截类来进行对EF6每一次向数据库发SQL请求的时候进行拦截记录日志或者发一个模拟的短暂错误;

这个类必须继承自 DbCommandInterceptor

在DAL文件夹新建 SchoolInterceptorLogging类,集成自DbCommandInterceptor

using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure.Interception;
using System.Data.Entity.SqlServer;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
using EFTest.Logging; namespace EFTest.DAL
{
public class SchoolInterceptorLogging : DbCommandInterceptor
{
private ILogger _logger = new Logger();
private readonly Stopwatch _stopwatch = new Stopwatch(); public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
base.ScalarExecuting(command, interceptionContext);
_stopwatch.Restart();
} public override void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
_stopwatch.Stop();
if (interceptionContext.Exception != null)
{
_logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText);
}
else
{
_logger.TraceApi("SQL Database", "SchoolInterceptor.ScalarExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText);
}
base.ScalarExecuted(command, interceptionContext);
} public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
base.NonQueryExecuting(command, interceptionContext);
_stopwatch.Restart();
} public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
_stopwatch.Stop();
if (interceptionContext.Exception != null)
{
_logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText);
}
else
{
_logger.TraceApi("SQL Database", "SchoolInterceptor.NonQueryExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText);
}
base.NonQueryExecuted(command, interceptionContext);
} public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
base.ReaderExecuting(command, interceptionContext);
_stopwatch.Restart();
}
public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
_stopwatch.Stop();
if (interceptionContext.Exception != null)
{
_logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText);
}
else
{
_logger.TraceApi("SQL Database", "SchoolInterceptor.ReaderExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText);
}
base.ReaderExecuted(command, interceptionContext);
}
}
}

另外,为了模拟在筛选查询的时候产生一个短暂错误,写一个类让用户在输入框内输入 Throw 的触发这个错误,在DAL文件夹里建SchoolInterceptorTransientErrors类:

重载了ReaderExecuting方法,当用户输入的是Throw的时候,做一个特殊处理来进行测试;

如果希望测试其他数据库操作,则可以考虑重载 NonQueryExecutingScalarExecuting这两个方法。

using System;
using System.Data.Common;
using System.Data.Entity.Infrastructure.Interception;
using System.Data.SqlClient;
using System.Reflection;
using System.Linq;
using EFTest.Logging; namespace EFTest.DAL
{
public class SchoolInterceptorTransientErrors : DbCommandInterceptor
{
private int _counter = ;
private ILogger _logger = new Logger(); public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
bool throwTransientErrors = false;
if (command.Parameters.Count > && command.Parameters[].Value.ToString() == "%Throw%")
{
throwTransientErrors = true;
command.Parameters[].Value = "%an%";
command.Parameters[].Value = "%an%";
} if (throwTransientErrors && _counter < )
{
_logger.Information("Returning transient error for command: {0}", command.CommandText);
_counter++;
interceptionContext.Exception = CreateDummySqlException();
}
} private SqlException CreateDummySqlException()
{
// The instance of SQL Server you attempted to connect to does not support encryption
var sqlErrorNumber = ; var sqlErrorCtor = typeof(SqlError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Where(c => c.GetParameters().Count() == ).Single();
var sqlError = sqlErrorCtor.Invoke(new object[] { sqlErrorNumber, (byte), (byte), "", "", "", }); var errorCollection = Activator.CreateInstance(typeof(SqlErrorCollection), true);
var addMethod = typeof(SqlErrorCollection).GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic);
addMethod.Invoke(errorCollection, new[] { sqlError }); var sqlExceptionCtor = typeof(SqlException).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Where(c => c.GetParameters().Count() == ).Single();
var sqlException = (SqlException)sqlExceptionCtor.Invoke(new object[] { "Dummy", errorCollection, null, Guid.NewGuid() }); return sqlException;
}
}
}

在Global.asax中添加声明:
using System.Data.Entity.Infrastructure.Interception;

并在Application_Start()方法中增加后面两行代码:

        protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
//Database.SetInitializer<SchoolContext>(new SchoolInitializer());
DbInterception.Add(new SchoolInterceptorTransientErrors());
DbInterception.Add(new SchoolInterceptorLogging());
}

当然,这两行代码可以加在SchoolConfiguration类里,初始化的时候直接加载执行:(注:上面和下面两段代码只能选其中一种

using System.Data.Entity;
using System.Data.Entity.Infrastructure.Interception;
using System.Data.Entity.SqlServer; namespace EFTest.DAL
{
public class SchoolConfiguration : DbConfiguration
{
public SchoolConfiguration()
{
SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
DbInterception.Add(new SchoolInterceptorTransientErrors());
DbInterception.Add(new SchoolInterceptorLogging());
}
}
}

下面就可以进行测试了,进Home/Index后点Students,进入Student/Index 就会发现VS 的Output 窗口有一些Debug信息输出:

SELECT Count(*)
FROM INFORMATION_SCHEMA.TABLES AS t
WHERE t.TABLE_SCHEMA + '.' + t.TABLE_NAME IN ('dbo.Course','dbo.Enrollment','dbo.Student')
OR t.TABLE_NAME = 'EdmMetadata':
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.RemoteDependency","time":"2017-08-25T07:04:11.0689220Z","tags":{"ai.internal.sdkVersion":"rddf: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index","ai.operation.parentId":"yqYB5YWz4YY=","ai.operation.id":"yqYB5YWz4YY="},"data":{"baseType":"RemoteDependencyData","baseData":{"ver":,"name":"(localdb)\\ProjectsV13 | master","id":"+xoBYBiNrPM=","value":0.3565,"dependencyKind":,"success":true,"properties":{"DeveloperMode":"true"}}}}
iisexpress.exe Information: : Component:SQL Database;Method:SchoolInterceptor.ScalarExecuted;Timespan:::00.0233412;Properties:Command: IF db_id(N'EFTest') IS NOT NULL SELECT ELSE SELECT Count(*) FROM sys.databases WHERE [name]=N'EFTest':
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.RemoteDependency","time":"2017-08-25T07:04:11.2577658Z","tags":{"ai.internal.sdkVersion":"rddf: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index","ai.operation.parentId":"yqYB5YWz4YY=","ai.operation.id":"yqYB5YWz4YY="},"data":{"baseType":"RemoteDependencyData","baseData":{"ver":,"name":"(localdb)\\ProjectsV13 | EFTest","id":"hGEE5js+frc=","value":1.2592,"dependencyKind":,"success":true,"properties":{"DeveloperMode":"true"}}}}
iisexpress.exe Information: : Component:SQL Database;Method:SchoolInterceptor.ReaderExecuted;Timespan:::00.0260725;Properties:Command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[__MigrationHistory] AS [Extent1]
WHERE [Extent1].[ContextKey] = @p__linq__0
) AS [GroupBy1]:
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.RemoteDependency","time":"2017-08-25T07:04:11.3081972Z","tags":{"ai.internal.sdkVersion":"rddf: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index","ai.operation.parentId":"yqYB5YWz4YY=","ai.operation.id":"yqYB5YWz4YY="},"data":{"baseType":"RemoteDependencyData","baseData":{"ver":,"name":"(localdb)\\ProjectsV13 | EFTest","id":"ULROylXtnGQ=","value":1.6166,"dependencyKind":,"success":true,"properties":{"DeveloperMode":"true"}}}}
iisexpress.exe Information: : Component:SQL Database;Method:SchoolInterceptor.ReaderExecuted;Timespan:::00.0155956;Properties:Command: SELECT TOP ()
[Project1].[C1] AS [C1],
[Project1].[MigrationId] AS [MigrationId],
[Project1].[Model] AS [Model],
[Project1].[ProductVersion] AS [ProductVersion]
FROM ( SELECT
[Extent1].[MigrationId] AS [MigrationId],
[Extent1].[Model] AS [Model],
[Extent1].[ProductVersion] AS [ProductVersion],
AS [C1]
FROM [dbo].[__MigrationHistory] AS [Extent1]
WHERE [Extent1].[ContextKey] = @p__linq__0
) AS [Project1]
ORDER BY [Project1].[MigrationId] DESC:
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.RemoteDependency","time":"2017-08-25T07:04:11.3703060Z","tags":{"ai.internal.sdkVersion":"rddf: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index","ai.operation.parentId":"yqYB5YWz4YY=","ai.operation.id":"yqYB5YWz4YY="},"data":{"baseType":"RemoteDependencyData","baseData":{"ver":,"name":"(localdb)\\ProjectsV13 | EFTest","id":"/xZUhdnSdM8=","value":1.7563,"dependencyKind":,"success":true,"properties":{"DeveloperMode":"true"}}}}
iisexpress.exe Information: : Component:SQL Database;Method:SchoolInterceptor.ReaderExecuted;Timespan:::00.0176946;Properties:Command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
) AS [GroupBy1]:
'iisexpress.exe' (CLR v4.0.30319: /LM/W3SVC//ROOT--): Loaded 'EntityFrameworkDynamicProxies-EFTest'.
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.RemoteDependency","time":"2017-08-25T07:04:11.4280626Z","tags":{"ai.internal.sdkVersion":"rddf: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index","ai.operation.parentId":"yqYB5YWz4YY=","ai.operation.id":"yqYB5YWz4YY="},"data":{"baseType":"RemoteDependencyData","baseData":{"ver":,"name":"(localdb)\\ProjectsV13 | EFTest","id":"bDKxb2FBJ1g=","value":0.9676,"dependencyKind":,"success":true,"properties":{"DeveloperMode":"true"}}}}
iisexpress.exe Information: : Component:SQL Database;Method:SchoolInterceptor.ReaderExecuted;Timespan:::00.0194244;Properties:Command: SELECT
[Extent1].[ID] AS [ID],
[Extent1].[LastName] AS [LastName],
[Extent1].[FirstMidName] AS [FirstMidName],
[Extent1].[EnrollmentDate] AS [EnrollmentDate]
FROM [dbo].[Student] AS [Extent1]
ORDER BY [Extent1].[LastName] ASC
OFFSET ROWS FETCH NEXT ROWS ONLY :
'iisexpress.exe' (CLR v4.0.30319: /LM/W3SVC//ROOT--): Loaded 'C:\Users\jaczhang\AppData\Local\Temp\Temporary ASP.NET Files\root\644be5f6\480b064f\App_Web_jlggwjiw.dll'.
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.Request","time":"2017-08-25T07:04:10.5173746Z","tags":{"ai.operation.id":"yqYB5YWz4YY=","ai.internal.sdkVersion":"web: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index"},"data":{"baseType":"RequestData","baseData":{"ver":,"id":"yqYB5YWz4YY=","name":"GET Student/Index","startTime":"2017-08-25T15:04:10.5173746+08:00","duration":"00:00:01.6326287","success":true,"responseCode":"","url":"http://localhost:9910/Student","httpMethod":"GET","properties":{"DeveloperMode":"true"}}}}

然后在筛选输入框输入Throw 点确定: 可以看到里面触发一个 代码为20的短暂错误:

iisexpress.exe Information:  : Returning transient error for command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1]
iisexpress.exe Error: : Error executing command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1] Exception: System.Data.SqlClient.SqlException (0x80131904): Dummy
ClientConnectionId:9b424f7d-306b-450b-8a3e-58198487b8bb
Error Number:,State:,Class:
iisexpress.exe Information: : Returning transient error for command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1]
iisexpress.exe Error: : Error executing command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1] Exception: System.Data.SqlClient.SqlException (0x80131904): Dummy
ClientConnectionId:941ac661-66d3--a690-188d13144150
Error Number:,State:,Class:
iisexpress.exe Information: : Returning transient error for command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1]
iisexpress.exe Error: : Error executing command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1] Exception: System.Data.SqlClient.SqlException (0x80131904): Dummy
ClientConnectionId:47685ec4-e837-4e05-bbb3-948e3f3f87a8
Error Number:,State:,Class:
iisexpress.exe Information: : Returning transient error for command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1]
iisexpress.exe Error: : Error executing command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1] Exception: System.Data.SqlClient.SqlException (0x80131904): Dummy
ClientConnectionId:35de62b7-cda6-4db7-88e0-48d708f42826
Error Number:,State:,Class:
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.RemoteDependency","time":"2017-08-25T07:06:51.9163289Z","tags":{"ai.internal.sdkVersion":"rddf: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index","ai.operation.parentId":"kZm9/0YA8y4=","ai.operation.id":"kZm9/0YA8y4="},"data":{"baseType":"RemoteDependencyData","baseData":{"ver":,"name":"(localdb)\\ProjectsV13 | EFTest","id":"0iOb6Vj5zqI=","value":3.3859,"dependencyKind":,"success":true,"properties":{"DeveloperMode":"true"}}}}
iisexpress.exe Information: : Component:SQL Database;Method:SchoolInterceptor.ReaderExecuted;Timespan:::00.0382038;Properties:Command: SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT() AS [A1]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [GroupBy1]:
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.RemoteDependency","time":"2017-08-25T07:06:51.9705260Z","tags":{"ai.internal.sdkVersion":"rddf: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index","ai.operation.parentId":"kZm9/0YA8y4=","ai.operation.id":"kZm9/0YA8y4="},"data":{"baseType":"RemoteDependencyData","baseData":{"ver":,"name":"(localdb)\\ProjectsV13 | EFTest","id":"b1S5ExJ8ugQ=","value":2.5604,"dependencyKind":,"success":true,"properties":{"DeveloperMode":"true"}}}}
iisexpress.exe Information: : Component:SQL Database;Method:SchoolInterceptor.ReaderExecuted;Timespan:::00.0195543;Properties:Command: SELECT
[Project1].[ID] AS [ID],
[Project1].[LastName] AS [LastName],
[Project1].[FirstMidName] AS [FirstMidName],
[Project1].[EnrollmentDate] AS [EnrollmentDate]
FROM ( SELECT
[Extent1].[ID] AS [ID],
[Extent1].[LastName] AS [LastName],
[Extent1].[FirstMidName] AS [FirstMidName],
[Extent1].[EnrollmentDate] AS [EnrollmentDate]
FROM [dbo].[Student] AS [Extent1]
WHERE ([Extent1].[LastName] LIKE @p__linq__0 ESCAPE N'~') OR ([Extent1].[FirstMidName] LIKE @p__linq__1 ESCAPE N'~')
) AS [Project1]
ORDER BY [Project1].[LastName] ASC
OFFSET ROWS FETCH NEXT ROWS ONLY :
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.Request","time":"2017-08-25T07:06:40.0512275Z","tags":{"ai.operation.id":"kZm9/0YA8y4=","ai.internal.sdkVersion":"web: 2.0.0.25000","ai.device.roleInstance":"chnsbopc02.dc01.fujixerox.net","ai.operation.name":"GET Student/Index"},"data":{"baseType":"RequestData","baseData":{"ver":,"id":"kZm9/0YA8y4=","name":"GET Student/Index","startTime":"2017-08-25T15:06:40.0512275+08:00","duration":"00:00:11.9404844","success":true,"responseCode":"","url":"http://localhost:9910/Student?SearchString=Throw","httpMethod":"GET","properties":{"DeveloperMode":"true"}}}}

为了看Retry是否其作用,可以先注释掉以下行:
  public SchoolConfiguration()
        {
            //SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());           
        }

然后再进入网页,输入Throw后点确定,就会发现出现了数据库错误:

看起来是起作用了;

最后记得把刚才注释掉的行取消注释。

【EF6学习笔记】(四)弹性连接及命令拦截调试的更多相关文章

  1. EF6学习笔记(四) 弹性连接及命令拦截调试

    EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本章原文地址:Connection Resiliency and Command Interception 原文 ...

  2. [翻译][MVC 5 + EF 6] 4:弹性连接和命令拦截

    原文:Connection Resiliency and Command Interception with the Entity Framework in an ASP.NET MVC Applic ...

  3. Monkey学习笔记<四>:Monkey服务器命令

    #使用如下命令将本地pc和手机连接起来 adb shell monkey --port 1080 adb forward tcp 1080:tcp 1080 telnet localhost 1080 ...

  4. 【linux学习笔记四】文件搜索命令

    一 文件搜索 locate //在后台数据库中按文件名搜索 搜索速度更快 locate 文件名 //locate命令所搜索的后台数据库 /var/lib/mlocate //更新数据库 updated ...

  5. 【EF6学习笔记】目录

    [EF6学习笔记](一)Code First 方式生成数据库及初始化数据库实际操作 [EF6学习笔记](二)操练 CRUD 增删改查 [EF6学习笔记](三)排序.过滤查询及分页 [EF6学习笔记]( ...

  6. ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)

    个人从传统的CS应用开发(WPF)开始转向BS架构应用开发: 先是采用了最容易上手也是最容易搞不清楚状况的WebForm方式入手:到后面就直接抛弃了服务器控件的开发方式,转而采用 普通页面+Ajax+ ...

  7. openresty 学习笔记四:连接mysql和进行相关操作

    openresty 学习笔记四:连接mysql和进行相关操作 毕竟redis是作为缓存,供程序的快速读写,虽然reidis也可以做持久化保存,但还是需要一个做数据存储的数据库.比如首次查询数据在red ...

  8. EF6学习笔记(六) 创建复杂的数据模型

    EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇原文地址:Creating a More Complex Data Model 本篇讲的比较碎,很多内容本人 ...

  9. EF6 学习笔记(五):数据库迁移及部署

    EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 原文地址:Code First Migrations and Deployment 原文主要讲两部分:开发环境下 ...

随机推荐

  1. 今天我给你们推荐一本书《Linux就该这么学》!!!

    本书是由全国多名红帽架构师(RHCA)基于最新Linux系统共同编写的高质量Linux技术自学教程,极其适合用于Linux技术入门教程或讲课辅助教材,目前是国内最值得去读的Linux教材,也是最有价值 ...

  2. ubuntu 安装vue+element

    1.安装npm sudo apt install npm 检测安装npm -v 因为npm安装软件慢,可设置淘宝镜像 npm config set registry https://registry. ...

  3. [Java基础复习] -- x. 正则表达式的使用

    序号待定, 先用x占位表示 理论知识待完善, 先贴上代码 import java.util.regex.Matcher; import java.util.regex.Pattern; import ...

  4. [Java练习题] -- 1. 使用java打印杨辉三角

    package cn.fzm.demo1.array; import java.util.Scanner; /* * 需求:打印杨辉三角形(行数可以键盘录入) 1 1 1 1 2 1 1 3 3 1 ...

  5. CentOS7安装OpenLDAP+MySQL+PHPLDAPadmin

    安装环境:CentOS 7 1.安装和设置数据库 在CentOS7下,默认安装的数据库为MariaDB,属于MySQL数据库的一个分支,所以我还是使用了MariaDB.安装命令为: [root@loc ...

  6. webapi使用swagger出现“Cannot read property 'parameters' of null”

    前端时间在webapi项目使用swagger来提供接口文档及测试工具,按网上方法(http://wmpratt.com/swagger-and-asp-net-web-api-part-1)配置好之后 ...

  7. Centos6.5 安装MYSQL 5.5 -5.6.-5.7 一键yum快速安装 ,初始配置

    Centos6.5 安装MYSQL 5.5 ---5.6---5.7 一键yum快速安装 ,初始配置 第一步:安装mysql-5.5---- 5.6 ---- 5.7的yum源 [root@sv03 ...

  8. [转]Understand QoS at OpenSwitch

    danny http://dannykim.me/danny/57771 2014.02.11 14:34:58 (*.193.128.184) 592 >>> Purpose Th ...

  9. radio点击一下选中,再点击恢复未选状态

    radio点击一下选中,再点击恢复未选状态 实现方式1: <input   type="radio"   id="cat"   name="ca ...

  10. 深入理解JVM(二)——内存模型、可见性、指令重排序

    上一篇我们介绍了JVM的基本运行流程以及内存结构,对JVM有了初步的认识,这篇文章我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存 ...