EF Core, исключение недопустимого имени столбца после обновления с netcore2.2 до netcore3.1

Поскольку я обновился с .netcore2.2 до .netcore3.1, я столкнулся с новым странным исключением «Недопустимое имя столбца« TenantTemplateTypeID1 »». Пожалуйста, не '1', это не должно быть здесь. Нигде в коде НЕТ TenantTemplateTypeID1, поэтому я предполагаю, что он сгенерирован ядром EF.

Основная версия EF: 3.1.1

Исключение:

Exception: Invalid column name 'TenantTemplateTypeID1'.
Invalid column name 'TenantTemplateTypeID1'.
Invalid column name 'TenantTemplateTypeID1'.
Invalid column name 'TenantTemplateTypeID1'.
StactTrace:    at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData()

Запрос:

var t = engineCtx.TenantTemplates
                 .AsNoTracking()
                 .Include(tt => tt.TenantTemplateParameters)
                 .Include(tt => tt.TenantTemplateStyles)
                 .FirstOrDefault(tt => tt.TenantTemplateTypeID == tenantTemplateTypeID);

Дбконтекст

modelBuilder.Entity<Db.Model.TenantTemplate>(entity =>
            {
                entity.HasKey(e => e.TenantTemplateTypeID)
                      .HasName("PK_TenantTemplate_TenantTemplateTypeID");

                entity.ToTable("TenantTemplates", "templateEngine");

                entity.Property(e => e.TenantTemplateTypeID)
                      .HasColumnName("TenantTemplateTypeId");
                //... not related rows removed
                entity.HasMany(e => e.TenantTemplateParameters)
                      .WithOne(e => e.TenantTemplate)
                      .HasConstraintName("FK_TenantTemplate_TenantTemplateParameters")
                      .OnDelete(DeleteBehavior.Restrict);

                entity.HasMany(e => e.TenantTemplateStyles)
                      .WithOne(e => e.TenantTemplate)
                      .HasConstraintName("FK_TenantTemplate_TenantTemplateStyles")
                      .OnDelete(DeleteBehavior.Restrict);
            });

Модель БД содержит только свойства без атрибутов.

public partial class TenantTemplate
    {
         public long TenantTemplateTypeID { get; set; }
         // not related rows removed
         public virtual ICollection<TenantTemplateParameter> TenantTemplateParameters { get; set; }
         public virtual ICollection<TenantTemplateStyle> TenantTemplateStyles { get; set; }
    }
// TenantTemplateStyle is exacly the same (just PK has a different name)
public class TenantTemplateParameter
   {
        public long TenantTemplateParameterID { get; set; }
        public long TenantTemplateTypeID { get; set; }
        // rows removed
        public virtual TenantTemplate TenantTemplate { get; set; }
   }

Кто-нибудь знает какой-нибудь перебор? Спасибо...


person Tomino    schedule 03.02.2020    source источник
comment
Можете выложить TenantTemplateParameter или TenantTemplateStyle класс - проблема должна быть там.   -  person Ivan Stoev    schedule 03.02.2020
comment
Вопрос обновлен...   -  person Tomino    schedule 04.02.2020


Ответы (1)


Я почти уверен, что это вызвано следующим критическим изменением EF Core 3.0 — Соглашение о свойствах внешнего ключа больше не совпадает имя в качестве основного свойства.

Согласно этому правилу, TenantTemplateTypeID в TenantTemplateParameter не считается именем FK.

Странно то, что в то же время это обычное имя FK по умолчанию в соответствии с правилами, описанными в Свойства тени внешнего ключа:

Свойство будет называться <navigation property name><principal key property name> (для именования используется навигация по зависимой сущности, которая указывает на основную сущность). Если имя свойства основного ключа включает имя свойства навигации, тогда имя будет просто <principal key property name>. Если в зависимом объекте нет свойства навигации, то вместо него используется имя основного типа. .

Поскольку имя уже зарезервировано свойством «не FK», обычный построитель имен добавляет индекс к обычному имени по умолчанию, отсюда и наблюдаемое поведение.

Я бы рассматривал это как ошибку/недостаток текущей реализации EF Core. Обходной путь/решение, конечно, состоит в том, чтобы явно отображать свойство FK, например.

entity.HasMany(e => e.TenantTemplateParameters)
      .WithOne(e => e.TenantTemplate)
      .HasForeignKey(e => e.TenantTemplateTypeID) // <--
      .HasConstraintName("FK_TenantTemplate_TenantTemplateParameters")
      .OnDelete(DeleteBehavior.Restrict);

и аналогично для другого отношения (с TenantTemplateStyle), если оно использует то же соглашение об именах.

person Ivan Stoev    schedule 04.02.2020