Обновление до 2.1 ломает существующую логику EF ядра .NET

У меня есть 2 объекта с отношением FK между ними. Вся эта логика отлично работала, когда я использовал .net core 2, но сломалась, когда я обновился до 2.1.

public class Parent
{
     [Key()]
     public Guid ParentGUID {get;set;}
     public string SomeValue {get;set;}
     [ForeignKey("ReferenceTypeGUID")]
     public ReferenceType ReferenceTypeObject {get;set;}
}
public class ReferenceType
{
     [Key()]
     public Guid ReferenceTypeGUID{get;set;}
     public string SomeOtherValue {get;set;}
     public virtual ICollection<Parent> ParentGU { get; set; }
}

а затем в моем dbcontext у меня есть

 modelBuilder.Entity<ReferenceType>(entity =>
        {
            entity.HasKey(e => e.ReferenceTypeGUID);

                entity.HasMany(c => c.ParentGU)
                    .WithOne(e => e.ReferenceTypeObject)
                    .HasForeignKey(f => f.ParentGUID)
                    .OnDelete(DeleteBehavior.ClientSetNull);
});

Теперь в моем исходном коде у меня не было строки HasForeignKey, и я получил следующую ошибку:

невозможно настроить таргетинг на первичный ключ, потому что он несовместим

добавление этой строки устранило эту проблему, но теперь я получаю

Конфликт типов операндов: int несовместим с uniqueidentifier

по какой-то причине EF предполагает, что тип базы данных должен быть int, а не uniqueidentifier, даже если объект объявлен как GUID. как мне исправить эту проблему?


person Phil    schedule 04.06.2018    source источник
comment
Не могли бы вы исправить образец (он не компилируется). Также очевидно, что PK ParentGUID не может использоваться как FK для отношений «многие к одному», поэтому сохраните исходный код и исходную проблему с обновлением.   -  person Ivan Stoev    schedule 04.06.2018
comment
Я предполагаю, что под net core 2.1 вы имеете в виду Entity Framework Core 2.1. Невозможно воспроизвести с помощью предоставленного кода (даже если я удалю явно неправильную строку .HasForeignKey). Попробуйте воспроизвести его в чистом проекте и дайте нам знать, или проверьте код, не показанный здесь, на предмет других причин.   -  person Ivan Stoev    schedule 04.06.2018
comment
См. github.com/vishnu4/EFCore21Test. просто запустите добавление-миграцию, и вы увидите ошибку: отношение от 'Parent.ReferenceTypeObject' к 'ReferenceType.ParentGU' со свойствами внешнего ключа {'ReferenceTypeGUID': Nullable ‹int›} не может нацеливаться на первичный ключ {' ReferenceTypeGUID ': Guid}, потому что он несовместим. Настройте основной ключ или набор совместимых свойств внешнего ключа для этой связи.   -  person Phil    schedule 04.06.2018
comment
Спасибо, воспроизведено!   -  person Ivan Stoev    schedule 04.06.2018
comment
У вас нет свойства в Parent, которое содержит ссылку на внешний ключ. Ваш родительский класс должен иметь свойство public Guid ReferenceTypeGUID { get; set; }. Я думаю, вы обнаружите, что атрибут [ForeignKey] ожидает найти объявленное имя свойства в том же классе.   -  person Brad    schedule 05.06.2018
comment
существует объект ссылочного типа, который фактически выполняет эту роль, вам не нужен фактический GUID. и, как я сказал изначально, это работало нормально, как написано в версии 2.0, только обновление до версии 2.1 вызвало проблему. См. Ответ ниже   -  person Phil    schedule 05.06.2018


Ответы (1)


Похоже, в EF Core 2.1 появилась ошибка, когда вы определяете свойство shadow FK через аннотацию ForeignKey (честно говоря, я не знал, что это вообще поддерживается). Он неправильно предполагает тип int или int? для этого теневого свойства, а не учитывает ссылочный тип свойства PK.

При желании вы можете указать проблему в их системе отслеживания проблем. Но я не рекомендую использовать для этой цели атрибут ForeignKey (или вообще аннотации данных для отношений).

Вы можете исправить это, добавив следующее в конфигурацию Parent entity fluent:

entity.Property<Guid?>("ReferenceTypeGUID");

но это имеет смысл, если вы хотите настроить, скажем, другое имя столбца базы данных для свойства shadow.

Лучшим (IMO) способом является удалить атрибут ForeignKey и просто использовать перегрузку HasForeignKey с параметром string foreignKeyPropertyNames:

entity.HasMany(c => c.ParentGU)
    .WithOne(e => e.ReferenceTypeObject)
    .HasForeignKey("ReferenceTypeGUID") // <--
    .OnDelete(DeleteBehavior.ClientSetNull);
person Ivan Stoev    schedule 04.06.2018
comment
это сделало это для меня, спасибо. Да, почему-то добавление атрибута ForeignKey в бизнес-объект кажется мне более понятным. Мне нравится добавлять к бизнес-объекту как можно больше и, если возможно, использовать OnModelCreating в минимальном объеме, но спасибо за то, что помогли мне заставить его работать! - person Phil; 04.06.2018