【问题标题】:Miniprofiler breaks on missing CreatedOn columnMiniprofiler 在缺少 CreatedOn 列时中断
【发布时间】:2014-05-10 23:16:33
【问题描述】:

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

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

附加信息:列名“CreatedOn”无效。

为什么会这样?我过去有 EF 5,并在 6.1 上升级到版本 6 及更高版本。

This 和 this 帖子有一些解决方法,并且还说当您从 4.3 版升级时会发生这种情况。在我的网络应用中,情况并非如此。

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

【问题讨论】:

  • 我知道解决方法/链接。但是,问题是如何通过不解决它来解决它(意味着没有解决方法)。
  • 您是否可以提供有关异常的更多信息?也许还有一些源代码?
  • 您可以在使用 EF 6 和 miniprofiler EF 6 的任何项目中重现这一点。并在 HomeController 中的 Index() ActionResult 中进行数据库调用(例如 dbContext.Users)。确保您已配置 miniprofiler(例如 MiniProfilerEF6.Initialize() in global.asax.cs。
  • @Quoter MiniProfiler 存储库中的 Sample.Mvc 项目中不会出现此错误。所以它不仅仅是使用 EF6 和 MP.EF6。我在代码优先(参见 Sample.Mvc)和 Db 优先场景中都使用了 MP.EF6,但还没有看到这个错误。您可以提供的任何更多信息来导致这种情况发生都会有所帮助。

标签: c# entity-framework mvc-mini-profiler


【解决方案1】:

我认为调试器中断是因为 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. 打开“异常”对话框(菜单调试/异常)
  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 引用。

【讨论】:

  • 我使用MSSQL 作为数据库存储。如果取消选中该框,是否会阻止所有其他发生的 SqlCeException 异常被抛出?
  • 我想你的意思是你正在使用 Sql Server。在这种情况下,您应该取消选中System.Data.SqlClient.SqlException(在System.Data.SqlClient 下)。这不会阻止抛出异常,这只会指示调试器在抛出异常时不要中断。
  • 我添加了一个构建后事件来删除 PDB,它似乎运行良好:del "$(TargetDir)MiniProfiler.pdb" /q /s
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-13
  • 2019-04-29
  • 1970-01-01
  • 2015-08-25
  • 2021-07-20
  • 1970-01-01
相关资源
最近更新 更多