简体   繁体   English

EF6 AssociationType多对多表上的System.InvalidOperationException

[英]System.InvalidOperationException on EF6 AssociationType Many-To-Many Table

I'm using EF6 Migrations Code First Conventions to rename all of my tables, properties, schemas, etc to fit our internal DB conventions. 我正在使用EF6迁移代码优先约定来重命名我的所有表,属性,模式等,以适合我们的内部数据库约定。 The Convention renames all of the fields and table names properly, compiles, and scaffolds as expected. 公约正确地重命名了所有的字段和表名称,按预期进行编译和脚手架。 However, when I go to update database, I get the following error: 但是,当我更新数据库时,出现以下错误:

System.InvalidOperationException: Sequence contains no matching element
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
   at System.Data.Entity.Migrations.DbMigrator.FillInForeignKeyOperations(IEnumerable`1 operations, XDocument targetModel)
   at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, VersionedModel targetModel, IEnumerable`1 operations, IEnumerable`1 systemOperations, Boolean downgrading, Boolean auto)
   at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration)
   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 no matching element

Here is the Migration Code for the table that's causing the issue. 这是导致此问题的表的迁移代码。 I've validated that PK's are correct, the ForeignKey tables exist and the types are correct, the indexes point to the right fields, etc. I'm all out of ideas here. 我已经验证PK正确,外键表存在并且类型正确,索引指向正确的字段等。在这里,我全都没有想法。

CreateTable(
            "cw.map_cw_service_cw_immunization",
            c => new
                {
                    cw_service_id = c.String(nullable: false, maxLength: 36),
                    cw_immunization_id = c.String(nullable: false, maxLength: 36),
                })
            .PrimaryKey(t => new { t.cw_service_id, t.cw_immunization_id })
            .ForeignKey("cw.careware_services", t => t.cw_service_id, cascadeDelete: true)
            .ForeignKey("cw.careware_immunizations", t => t.cw_immunization_id, cascadeDelete: true)
            .Index(t => t.cw_service_id, name: "IX_CarewareService_Id")
            .Index(t => t.cw_immunization_id, name: "IX_CarewareImmunization_Id");

    }

UPDATE: I've narrowed the issue down to a foreign key problem. 更新:我已将问题缩小为外键问题。 If I comment out the two foreign key extension methods, the database updates as expected. 如果我注释掉这两种外键扩展方法,数据库将按预期更新。 However, obviously that isn't a valid workaround as now the table has no FK constraints. 但是,显然这不是一个有效的解决方法,因为该表现在没有FK约束。

I did some digging based on the error stack and found the method below in the EntityFramework source. 我根据错误堆栈进行了一些挖掘,并在EntityFramework源代码中找到了以下方法。 The error was caused by a Single() not returning a value. 该错误是由Single()未返回值引起的。 There is only one .Single() operation that doesn't return default, so that's obviously the culprit. 只有一个.Single()操作不会返回默认值,因此显然是罪魁祸首。 That operations returns the single EntityTypeElement that matches the EntitySetName (since they're supposed to be unique). 该操作返回与EntitySetName匹配的单个EntityTypeElement(因为它们应该是唯一的)。 Long story short, I realize that somewhere in my code I must be accidentally changing the EntitySet.Name value instead of the EntitySet.Table value. 长话短说,我意识到我必须在代码的某个地方意外地更改EntitySet.Name值而不是EntitySet.Table值。 Lo and behold, that was the culprit. 瞧,那是罪魁祸首。 I changed the line of code and it works just fine. 我更改了代码行,并且效果很好。

TL;DR; TL; DR; - Always check to make sure you're setting the EntitySet.Table value and not changing the EntitySet.Name value in your convetions. -始终检查以确保您正在设置EntitySet.Table值,并且在更改时未更改EntitySet.Name值。

private void FillInForeignKeyOperations(IEnumerable<MigrationOperation> operations, XDocument targetModel)
{
    DebugCheck.NotNull(operations);
    DebugCheck.NotNull(targetModel);

    foreach (var foreignKeyOperation
        in operations.OfType<AddForeignKeyOperation>()
                     .Where(fk => fk.PrincipalTable != null && !fk.PrincipalColumns.Any()))
    {
        var principalTable = GetStandardizedTableName(foreignKeyOperation.PrincipalTable);
        var entitySetName
            = (from es in targetModel.Descendants(EdmXNames.Ssdl.EntitySetNames)
               where _modelDiffer.GetQualifiedTableName(es.TableAttribute(), es.SchemaAttribute())
                                 .EqualsIgnoreCase(principalTable)
               select es.NameAttribute()).SingleOrDefault();

        if (entitySetName != null) //ERROR SOURCE IS BELOW
        {
            var entityTypeElement
                = targetModel.Descendants(EdmXNames.Ssdl.EntityTypeNames)
                             .Single(et => et.NameAttribute().EqualsIgnoreCase(entitySetName)); 

            entityTypeElement
                .Descendants(EdmXNames.Ssdl.PropertyRefNames).Each(
                    pr => foreignKeyOperation.PrincipalColumns.Add(pr.NameAttribute()));
        }
        else
        {
            // try and find the table in the current list of ops
            var table
                = operations
                    .OfType<CreateTableOperation>()
                    .SingleOrDefault(ct => GetStandardizedTableName(ct.Name).EqualsIgnoreCase(principalTable));

            if ((table != null)
                && (table.PrimaryKey != null))
            {
                table.PrimaryKey.Columns.Each(c => foreignKeyOperation.PrincipalColumns.Add(c));
            }
            else
            {
                throw Error.PartialFkOperation(
                    foreignKeyOperation.DependentTable, foreignKeyOperation.DependentColumns.Join());
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM