【问题标题】:EF Core, table-per-hierarchy and referencing entity of the same base class generates errorEF Core、table-per-hierarchy 和引用同一基类的实体会产生错误
【发布时间】:2018-11-15 12:54:23
【问题描述】:

我们有联系人是通过每个层次结构的表存储的, 联系人可以是公司也可以是个人,而个人始终属于公司。 两者都继承自联系人。

使用的是 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 =&gt; c.Contact).FirstOrDefault();

这会产生以下异常

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

堆栈跟踪

 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 我加了sample repo

只需将 DbContextFactory 中的 ConnectionString 更改为您的本地路径即可。

【问题讨论】:

  • 无法重现(EF Core 2.1.4,SqlServer LocalDB)。
  • 你使用的是哪个 SqlServer 版本?
  • 本地数据库。在 Visual Studio 中的 Sql Server 对象资源管理器中显示 Sql Server 12.0.2000。
  • 我添加了一个演示行为的示例 repo

标签: c# entity-framework-core table-per-hierarchy


【解决方案1】:

我能够在 EF Core 2.1.4 和 2.2 预览版中使用提供的 repo 重现它。

正如您在上次更新中提到的,问题在某种程度上与延迟加载(代理?)有关,因为没有UseLazyLoadingProxies() 代码按预期工作(这就是我最初无法重现它的原因)。

由于这显然是 EF Core 错误,您只能将其报告给 EF Core Issue Tracker 并等待修复。不幸的是,您可能不会在即将发布的 2.2 版本中包含该功能,但谁知道呢,值得一试。

【讨论】:

    【解决方案2】:

    在我看来就像实体框架中的一个错误,但是您可以通过显式指定自动生成的属性来防止这种情况发生,例如将 CompanyId 属性显式添加到 Person 类中

    这将防止 EF Core 将生日列错误映射到 CompanyId 列

    public class Person : Base
    {
        // ...
    
        public virtual Company Company { set; get; }    
        public Guid? CompanyId { get; set; }
    }
    

    【讨论】:

    • 你去!好的解决方法,应该包含在错误报告中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多