Miniprofiler breaks on missing CreatedOn column
Asked Answered
T

1

11

I have miniprofiler installed in my web app (asp.net-mvc) for EF 6.1, and it breaks on a line with the following error message:

An exception of type 'System.Data.SqlClient.SqlException' occurred in MiniProfiler.dll but was not handled in user code

Additional information: Invalid column name 'CreatedOn'.

Why is this happening? I had EF 5 in the past and upgraded to version 6 and later on 6.1.

This and this post have some workarounds, and are also saying that this happens when you upgraded from version 4.3. That's not the case in my web app.

Does anyone actually fixed this bug by not working around it?

Tenuto answered 10/5, 2014 at 23:16 Comment(5)
community.miniprofiler.com/t/sqlexception-on-ef-5-w-net-4-5/71/…Salinas
I am aware of that work around/link. However, the question was how to fix it by not working around it (means no workaround).Tenuto
Is there more information you can provide about the exception? Maybe some source code as well?Southwester
You could reproduce this with any project using EF 6 in combination with miniprofiler EF 6. And do a database call in the Index() ActionResult in the HomeController (example dbContext.Users). Make sure you have configured miniprofiler (example MiniProfilerEF6.Initialize() in global.asax.cs.Tenuto
@Tenuto this error does not occur in the Sample.Mvc project in the MiniProfiler repo. So it is more than just using EF6 and MP.EF6. I have used MP.EF6 in both code first (see Sample.Mvc) and Db first scenarios and have not yet seen this error. Any more info that you can provide for causing this to occur would be helpful.Paper
N
11

I think that the debugger breaks because the PDB files are included in the MiniProfiler NuGet packages.

The break occurs when an exception is thrown by the entity framework as it tries to determine if the column CreatedOn exists in the __MigrationHistory table. (Code extracted using IlSpy from 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);
}

You can notice that if you manually create the column to avoid the exception, it will be removed on the next run and the exception will come back. As MiniProfiler interpose itself in DbCommand.ExecuteReader(), it is on the path of the exception before the catch (the linq query translates to a sql query, and is finally executed using a DbCommand).

You have two solution to prevent the break from occuring:

Disable breaks for that type of exception

You can disable breaking on a particular exception in the Visual Studio debugger. I'm working with Sql CE so I had first to declare the SqlCeException (step 2 to 4). If you are working with SqlServer you can probably skip this step, just check that the type of the exception that is thrown is already in the list.

  1. Open the 'Exceptions' dialog (menu Debug/Exceptions)
  2. 'Add...' button, select 'Common Language Runtime Exceptions' as type.
  3. Set the exception name to 'System.Data.SqlServerCe.SqlCeException'
  4. Validate and keep the 'Exceptions' dialog opened.
  5. Open the 'Common Language Runtime Exceptions' section in the list.
  6. Uncheck both check boxes in front of System.Data.SqlServerCe.SqlCeException (or the exception that is thrown in your case) and close the dialog.

The exception should not cause a break from now. However, the debugger will not break even in your own code, and if another type of exception is thrown by MiniProfiler in another case a break will occur again.

Remove the PDB files

You can remove the MiniProfiler PDB's files, but you will have to remove the NuGet references:

  1. Locate and make a copy of the MiniProfiler dll's (from your project's bin folder). Of course, do not make a copy of the pdb files.
  2. Remove all NuGet references to MiniProfiler.
  3. Add references to the dll's you have copied to a different folder.

The drawback is that you will not be able to use NuGet to update MiniProfiler.

Maybe a better solution would be to remove the PDB from the NuGet package, but I don't know if they are needed for another purpose.

Edit

As jrummell points it out in his comment, the PDB's files can be removed using a Post Build Event. That way you can keep your NuGet references.

Neall answered 14/5, 2014 at 7:53 Comment(3)
I'm using MSSQL as the database storage. If you uncheck that box, doesn't that stop all other SqlCeException exceptions happening from being thrown?Tenuto
I suppose that you mean that you are using Sql Server. In that case you should uncheck System.Data.SqlClient.SqlException (under System.Data.SqlClient). This will not prevent the exceptions from being throw, this will just instruct the debugger not to break when they are thrown.Neall
I added a Post Build Event to remove the PDB and it seems to work well: del "$(TargetDir)MiniProfiler.pdb" /q /sChally

© 2022 - 2024 — McMap. All rights reserved.