问题 Miniprofiler在缺少CreatedOn列时中断


我在我的网络应用程序中安装了miniprofiler(asp.net-mvc)对于EF 6.1,它在一行中断,出现以下错误消息:

发生了'System.Data.SqlClient.SqlException'类型的异常   MiniProfiler.dll但未在用户代码中处理

附加信息:无效的列名称'CreatedOn'。

为什么会这样?我过去使用EF 5并升级到版本6,后来升级到6.1。

这个 和 这个 post有一些解决方法,并且还说当你从4.3版本升级时会发生这种情况。在我的网络应用程序中并非如此。

有没有人通过不解决这个问题来修复这个错误?


4241
2018-05-10 23:16


起源

community.miniprofiler.com/t/sqlexception-on-ef-5-w-net-4-5/71/... - Oleksii Aza
我知道这个工作/链接。然而,问题是如何通过不解决它来解决它(意味着没有解决方法)。 - Quoter
您是否可以提供有关例外的更多信息?也许还有一些源代码? - BonanzaOne
您可以使用EF 6与miniprofiler EF 6结合使用任何项目来重现这一点。并在中进行数据库调用 Index()  ActionResult 在里面 HomeController (例 dbContext.Users)。确保你配置了miniprofiler(例子 MiniProfilerEF6.Initialize() 在global.asax.cs中。 - Quoter
@Quoter MiniProfiler仓库中的Sample.Mvc项目中不会发生此错误。所以它不仅仅是使用EF6和MP.EF6。我先在两个代码中使用了MP.EF6(参见Sample.Mvc)和Db第一个场景,但还没有看到这个错误。您可以提供的任何更多信息都会有所帮助。 - Yaakov Ellis


答案:


我认为调试器会中断,因为PDB文件包含在MiniProfiler NuGet包中。

当实体框架尝试确定列是否发生异常时,会发生中断 CreatedOn 存在于 __MigrationHistory 表。 (使用IlSpy提取的代码 System.Data.Entity.Migrations.History.HistoryRepository.GetUpgradeOperations()

bool flag = false;
try
{
    this.InjectInterceptionContext(legacyHistoryContext);
    using (new TransactionScope(TransactionScopeOption.Suppress))
    {
        (
            from h in legacyHistoryContext.History
            select h.CreatedOn).FirstOrDefault<DateTime>(); // Will throw an exception if the column is absent
    }
    flag = true;
}
catch (EntityException)
{
}
if (flag)
{
    // Remove the column if present (if no exception was thrown)
    yield return new DropColumnOperation("dbo.__MigrationHistory", "CreatedOn", null);
}

您可以注意到,如果您手动创建列以避免异常,它将在下次运行时被删除,异常将返回。 由于MiniProfiler将自己置于DbCommand.ExecuteReader()中,因此它位于catch之前的异常路径上(linq查询转换为sql查询,最后使用DbCommand执行)。

你有两个解决方案来防止发生中断:

禁用该类型的异常中断

您可以在Visual Studio调试器中禁用中断特定异常。 我正在使用Sql CE,所以我首先声明了 SqlCeException (步骤2到4)。如果您正在使用SqlServer,则可以跳过此步骤,只需检查引发的异常类型是否已在列表中。

  1. 打开'Exceptions'对话框(菜单Debug / Exceptions)
  2. '添加...'按钮,选择'公共语言运行时例外'作为类型。
  3. 将异常名称设置为'System.Data.SqlServerCe.SqlCeException'
  4. 验证并保持“异常”对话框打开。
  5. 打开列表中的“公共语言运行时例外”部分。
  6. 取消选中前面的两个复选框 System.Data.SqlServerCe.SqlCeException (或您的情况下抛出的异常)并关闭对话框。

该异常不应该导致从现在开始。 但是,调试器在您自己的代码中不会中断,如果MiniProfiler在另一种情况下抛出另一种类型的异常,则会再次发生中断。

删除PDB文件

您可以删除MiniProfiler PDB的文件,但您必须删除NuGet引用:

  1. 找到并制作MiniProfiler dll的副本(从项目的bin文件夹中)。当然,不要复制pdb文件。
  2. 删除所有对MiniProfiler的NuGet引用。
  3. 添加对已复制到其他文件夹的dll的引用。

缺点是您将无法使用NuGet更新MiniProfiler。

也许更好的解决方案是从NuGet包中删除PDB,但我不知道是否需要它们用于其他目的。

编辑

jrummell 在他的评论中指出,可以使用Post Build Event删除PDB的文件。这样你就可以保留你的NuGet引用。


11
2018-05-14 07:53



我在用着 MSSQL 作为数据库存储。如果取消选中该框,则不会停止所有其他框 SqlCeException 被抛出的异常? - Quoter
我想你的意思是你正在使用Sql Server。在这种情况下,你应该取消选中 System.Data.SqlClient.SqlException (下 System.Data.SqlClient)。这不会阻止抛出异常,这只会指示调试器在抛出时不会中断。 - Olivier Leneveu
我添加了一个Post Build Event以删除PDB,它似乎运行良好: del "$(TargetDir)MiniProfiler.pdb" /q /s - jrummell