EF Core, таблица на иерархию и ссылающаяся сущность одного и того же базового класса генерируют ошибку - PullRequest
0 голосов
/ 15 ноября 2018

У нас контакты хранятся через таблицу на иерархию, Контакт - это либо компания, либо человек, а человек всегда принадлежит компании. Оба наследуют от контакта.

EF Core 2.1 используется.

Это выглядит так

public abstract class Contact {
    public virtual Guid Id { get; set; }
    public virtual ICollection<Source> Sources{ set; get; } = new Collection<Source>();
}

public class Company : Contact {
    public string CompanyName { set; get; }
    public virtual ICollection<Person> People { set; get; } = new Collection<Person>();
}

public class Person: Contact {
    public string Name { set; get; }
    public DateTime Birthday { set; get; }
    public virtual Company Company { set; get; }
}

Пока все хорошо, что мы сейчас хотим сделать, это запросить Sources и включить contacts (все они, не имеет значения, человек или компания)

context.Contact.Include(c => c.Contact).FirstOrDefault();

Это генерирует следующее исключение

Unable to cast object of type 'System.DateTime' to type 'System.Nullable``1[System.Guid]'.'

StackTrace

 at lambda_method(Closure , ValueBuffer )
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalMixedEntityEntry..ctor(IStateManager stateManager, IEntityType entityType, Object entity, ValueBuffer& valueBuffer)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntryFactory.NewInternalEntityEntry(IStateManager stateManager, IEntityType entityType, Object entity, ValueBuffer& valueBuffer)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTrackingFromQuery(IEntityType baseEntityType, Object entity, ValueBuffer& valueBuffer, ISet`1 handledForeignKeys)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.StartTracking(Object entity, IEntityType entityType)
   at lambda_method(Closure , QueryContext , AdSourceCrm , Object[] )
   at Microsoft.EntityFrameworkCore.Query.Internal.IncludeCompiler._Include[TEntity](QueryContext queryContext, TEntity entity, Object[] included, Action`3 fixup)
   at lambda_method(Closure , TransparentIdentifier`2 )
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)
   at lambda_method(Closure )
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ResultEnumerable`1.GetEnumerator()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results, QueryContext queryContext, IList`1 entityTrackingInfos, IList`1 entityAccessors)+MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_1`1.<CompileQueryCore>b__0(QueryContext qc)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at EfTest.Program.Main(String[] args) in Program.cs:line 18

Мы уже потратили часы (больше как дни), пытаясь найти причину и устранить причину, но безрезультатно.

EF Core как-то отключается с нашей конструкцией (возможно, сама конструкция неправильна)

Если вы отключите LazyLoading, проблема исчезнет.

Есть идеи, в чем причина и что бы решить эту проблему?

РЕДАКТИРОВАТЬ 2 Я удаляю Sources, так как они, похоже, не связаны с проблемой

РЕДАКТИРОВАТЬ 3 Я добавил образец репо

Просто измените ConnectionString в DbContextFactory на ваш локальный путь.

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Мне кажется, что это ошибка в Entity Framework, однако вы можете предотвратить это, явно указав автоматически сгенерированные свойства, например, добавив свойство CompanyId в класс Person явным образом

Это предотвратит ошибочное отображение столбца «День рождения» в столбец CompanyId, выполненное EF Core

public class Person : Base
{
    // ...

    public virtual Company Company { set; get; }    
    public Guid? CompanyId { get; set; }
}
0 голосов
/ 29 ноября 2018

Мне удалось воспроизвести его с предоставленным репозиторием в предварительном просмотре EF Core 2.1.4 и 2.2.

Как вы упоминали в последнем обновлении, проблема как-то связана с отложенной загрузкой (прокси?)потому что без UseLazyLoadingProxies() код работает должным образом (поэтому я не смог воспроизвести его изначально).

Поскольку это явно ошибка EF Core, вы ничего не можете сделать, как сообщить о нейк EF Core Issue Tracker и дождитесь исправления.К сожалению, вероятно, вы не включите это в предстоящую версию 2.2, но кто знает, стоит попробовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...