Sequence contains more than one element

Easiest way to debug Seed-method in Code-first migrations in Entity Framework

This post was most recently updated on March 27th, 2019.

Reading Time: 4 minutes.

This post describes the easiest way to debug the issues that may stop your Seed-method in Configuration.cs from going through. This problem concerns typically your ASP.NET MVC projects, either on .NET Framework or .NET Core – the same basic idea should work for both situations.

The solution here shows you, how you can get a little bit more information out of the process, without attaching the debugger (there’s another blog post for that: How to launch the visual studio debugger from code/)

Description

Entity Framework’s code-first migration’s are a beautiful and easy way of managing database schema changes and populating some preliminary data there. Personally I also sometimes use the method for adding some enrichment to data or or custom property values mapping that would otherwise require an additional/external console program.

Problem: running the Seed-method is by default undebuggable

Okay – so seeding data is cool. You do that within your Configuration.cs -file when running Update-Database to insert some default or baseline data to your database.

That’s fine and dandy, but debugging the issues in the function while running Update-Database is NOT so cool. You can’t run the Seed-method with debugger turned on. Hence, when you run into issues, you only get the stacktrace and exception message – and that’s not always that informative.

In my other blog post, I describe how you CAN in fact debug the Seed-method, by launcing a debugger instance manually from the method itself. See the other solution here:

This blog post shows an alternative to that – you can also modify the error messages thrown during the Seed method!

See this:

update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending explicit migrations.
Running Seed method.
System.InvalidOperationException: Sequence contains more than one element
   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.<getelementfunction>b__2[TResult](IEnumerable`1 sequence)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   at System.Data.Entity.Migrations.DbSetMigrationsExtensions.AddOrUpdate[TEntity](DbSet`1 set, IEnumerable`1 identifyingProperties, InternalSet`1 internalSet, TEntity[] entities)
   at System.Data.Entity.Migrations.DbSetMigrationsExtensions.AddOrUpdate[TEntity](IDbSet`1 set, Expression`1 identifierExpression, TEntity[] entities)
   at ....Migrations.Configuration.Seed(ApplicationDbContext db) in C:\...\Migrations\Configuration.cs:line 345
   at System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext context)
   at System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
   at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<update>b__b()
   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
Sequence contains more than one element.

Okay, so “Sequence contains more than one element”. Cool. I’m probably failing an AddOrUpdate-call somewhere, but I hate going through the exception to find the Configuration.cs:345 (or similar) row that actually tells where the exception was, when I could have the exception tell me what went wrong. Unfortunately, the exception just shows me the message of the thrown exception – which is NOT descriptive.

Oh, but wait: There is a solution!

Solution

By wrapping the whole stuff in a try-catch -block, catching the thrown exception, wrapping a new exception with a custom message around it and including the original one as internal exception, we get the data from the original exception AND our custom message – which in my case tells how far in the Seed-method (or just in which part of seeding / mapping the data we are in) we’ve proceeded. You can even make it tell the line where we’ve gotten to!

So, in my Configuration.cs class (in Migrations), I have first this:

internal class Configuration : DbMigrationsConfiguration<applicationdbcontext>
    {
        private bool _debug = false;
 
        private string _customExceptionMessage = "";
 
...

Then, further down the line when seeding my data, I have these little calls:

db.Companies.AddOrUpdate(p =&gt; p.CompanyIdentifier,
	new Company
	{
		...
	},
	new Company
	{
		...
	}
);
db.SaveChanges();
_customExceptionMessage += "Companies saved ok;";

This goes on for a while, but I’ve wrapped the whole method in a try-catch, like below:

/// <summary>
/// This method will be called after migrating to the latest version.
/// </summary>
/// <param name="db">
protected override void Seed(ApplicationDbContext db)
{
	try
	{
		_customExceptionMessage += "Running Seed method in Configuration.cs;";
 
		db.Companies.AddOrUpdate(p =&gt; p.CompanyIdentifier,
			new Company
			{
				...
			},
			new Company
			{
				...
			}
		);
		db.SaveChanges();
		_customExceptionMessage += "Companies saved ok;"
 
		... 
	}
	catch (Exception ex)
	{
		Exception ex2 = new Exception(_customExceptionMessage, ex);
 
		throw ex2;
	}
}

Now the exception in the Package Manager Console will be something like this:

// Omitted for clarity
...
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
Running Seed method in Configuration.cs;Companies saved ok;User added to company ok;Contacts saved ok;

So, now you get this:

Running Seed method in Configuration.cs;Companies saved ok;User added to company ok;Contacts saved ok;

To let you know how far you got in the execution.

This is, at least to me, a small improvement. Pretty? Ha, no. Much faster than launching a debugger? Yes!

Also, very hack-ish, but better than the normal functionality. And combined with launching the debugger from the code (as described here), quite an improvement over just getting a stacktrace.

mm
0 0 vote
Article Rating
Subscribe
Notify of
guest
2 Comments
Inline Feedbacks
View all comments

[…] very little about the actual issue, and since debugging code-first migrations is kind of difficult (see the best tips for that here!), it’s cumbersome to […]

[…] very little about the actual issue, and since debugging code-first migrations is kind of difficult (see the best tips for that here!), it’s cumbersome to […]