![](/img/trans.png)
[英]Entity Framework Core Table-per-Hierarchy: Prevent "unregistered classes" from being added as base type
[英]EF Core, table-per-hierarchy and referencing entity of the same base class generates error
我們的聯系人是通過每個層次的表存儲的,聯系人是公司或個人,而一個人始終屬於公司。 兩者都從聯系繼承。
使用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
(所有contacts
,對於個人或公司而言都沒有關系)
context.Contact.Include(c => 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我添加了一個示例回購
只需將DbContextFactory中的ConnectionString更改為本地路徑即可。
我可以使用EF Core 2.1.4和2.2預覽版中提供的存儲庫來重現它。
正如您在上一次更新中提到的那樣,問題某種程度上與延遲加載(代理?)有關,因為沒有使用UseLazyLoadingProxies()
,代碼按預期工作了(這就是為什么我最初無法重現它的原因)。
由於這顯然是EF Core錯誤,因此您只能將其報告給EF Core問題跟蹤器並等待修復。 不幸的是,薄霧可能不會在即將發布的2.2版本中包含,但誰知道,值得嘗試。
在我看來,就像Entity Framework中的錯誤一樣,您可以通過顯式指定自動生成的屬性來防止這種情況發生,例如,將CompanyId屬性顯式添加到Person類
這樣可以防止EF Core將Birthday列錯誤映射到CompanyId列
public class Person : Base
{
// ...
public virtual Company Company { set; get; }
public Guid? CompanyId { get; set; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.