Sequence contains more than one element

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

This post was most recently updated on October 4th, 2022.

4 min read.

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 migrations 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 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 the 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 launching 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.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.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

Time needed: 15 minutes

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 an 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!

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

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

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

    <pre lang="csharp">db.Companies.AddOrUpdate(p => p.CompanyIdentifier,
                    new Company
                    {
                                    ...
                    },
                    new Company
                    {
                                    ...
                    }
    );
    db.SaveChanges();
    _customExceptionMessage += "Companies saved ok;";
    </pre>

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

    <pre lang="csharp">/// <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 => p.CompanyIdentifier,
                                                    new Company
                                                    {
                                                                    ...
                                                    },
                                                    new Company
                                                    {
                                                                    ...
                                                    }
                                    );
                                    db.SaveChanges();
                                    _customExceptionMessage += "Companies saved ok;"
                                   
                                    ...
                    }
                    catch (Exception ex)
                    {
                                    Exception ex2 = new Exception(_customExceptionMessage, ex);
     
                                    throw ex2;
                    }
    }
    </pre>

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

    <pre lang="csharp">// 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;</pre>

  5. So, now you get this:

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

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
4 2 votes
Article Rating
Subscribe
Notify of
guest

2 Comments
most voted
newest oldest
Inline Feedbacks
View all comments