[英]InvalidCastException when using IncludeFilter on entity with DateTime property"
我遇到了一個我不明白的 InvalidCastException,特別是與 Entity Framework Plus 庫及其 IncludeFilter 擴展方法有關。
總而言之,我有 3 個實體:項目、測試和測試運行: - 每個項目都有一個測試集合; - 每個測試都有一組測試運行。 我有一個 ProjectService 類,它實現了一種從數據庫中檢索項目的方法,並帶有用於選擇需要哪些包含的選項。 這是此方法的代碼(我將其分解為仍然產生相同異常的最小代碼段,以及另一段用於比較的代碼):
private IQueryable<Project> NewQuery(ProjectIncludeOptions includes = ProjectIncludeOptions.NONE)
{
IQueryable<Project> query = base.NewQuery();
/* NO PROBLEM HERE: just left it for comparison. */
if (includes.HasFlag(ProjectIncludeOptions.DOMAINS))
{
query =
query
.IncludeFilter(p => p.TestDomains.Where(td => !td.IsArchived).Select(td => td.Children.Where(tdc => !tdc.IsArchived)))
.IncludeFilter(p => p.TestDomains.Where(td => !td.IsArchived).Select(td => td.Parent));
}
/* EXCEPTION CAUSED BY THE CODE BELOW */
if (includes.HasFlag(ProjectIncludeOptions.TESTS))
{
query =
query
/* In the below code, if I remove the Where clause, or use a non-calculated property in it, then the exception disappears. */
.IncludeFilter(p => p.Tests.Where(t => !t.IsArchived).Select(t => t.TestRuns));
}
return query;
}
IsArchived 屬性的實現(在 Test 類中)如下:
[NotMapped]
public virtual bool IsArchived
{
get { return ArchivingDate.HasValue; }
set { ArchivingDate = value ? System.DateTime.Now : (System.DateTime?)null; }
}
以及我實際獲得 InvalidCastException 的地方(來自 SingleOrDefault 調用):
Project project = NewQuery(includes).SingleOrDefault(p => p.Id == projectId);
完整的異常消息是:
System.InvalidCastException:“無法將“System.String”類型的對象轉換為“System.Int32”類型。
以及發生錯誤時的堆棧跟蹤:
在 System.Data.SqlClient.SqlBuffer.get_Int32() 在 System.Data.SqlClient.SqlDataReader.GetInt32(Int32 i) 在 lambda_method(Closure , DbDataReader) 在 Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader) 在Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable
1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func
3 operation, Func3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable
1.Enumerator.MoveNext() 在 System.Linq.Lookup 2.CreateForJoin(2.CreateForJoin(IEnumerable
1 source, Func2 keySelector, IEqualityComparer
12 keySelector, IEqualityComparer
) at System.Linq.Enumerable.Joinable.Joinable. TOuter,TInner,TKey,TResult](IEnumerable1 outer, IEnumerable
2 outerKeySelector, Func
1 outer, IEnumerable
1 inner, Func2 outerKeySelector, Func
2 innerKeySelector, Func3 resultSelector, IEqualityComparer
1 comparer)+MoveNext() at System.Linq.Enum erable.GroupJoinIterator[TOuter,TInner,TKey,TResult](IEnumerable1 outer, IEnumerable
1 內,Func2 outerKeySelector, Func
1 outer, IEnumerable
鍵2 outerKeySelector, Func
2 內2 outerKeySelector, Func
選擇器,Func3 resultSelector, IEqualityComparer
1 比較器)+MoveNext() 在 System.Linq.Enumerable[。 TSource,TCollection,TResult](IEnumerable1 source, Func
2 collectionSelector, Func3 resultSelector)+MoveNext() at System.Linq.Enumerable.SelectEnumerableIterator
2.MoveNext() 在 Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut ,TIn](IEnumerable1 results, QueryContext queryContext, IList
1 entityTrackingInfos,IList1 entityAccessors)+MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor
1.EnumeratorExceptionInterceptor.MoveNext() 在 Z.EntityFramework.Plus.QueryFuture1.SetResult(IEnumerator
1 enumerator) 在 Z.EntityFramework.Plus.QueryFutureEnumerable1.SetResult(DbDataReader reader) at Z.EntityFramework.Plus.QueryFutureBatch.ExecuteQueries() at Z.EntityFramework.Plus.QueryFutureValue
1.SetResult(DbDataReader reader) at Z.EntityFramework.Plus.QueryFutureBatch.ExecuteQueries() at Z.EntityFramework.Plus.QueryFutureValue
1.get_Value() 在 Z.EntityFramework.Plus.QueryIncludeFilterProvider1.Execute[TResult](Expression expression) at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable
1 源,Expression`1謂詞)在 Tresse.Service.Impl.ProjectService.Get(Int32 projectId, ProjectIncludeOptions includes)
最讓我困惑的是,當我使用 ProjectIncludeOptions.DOMAINS 部分時,我沒有得到任何異常,這顯然是以完全相同的方式實現的(IsArchived 屬性在 TestDomain 對象上也是相同的)。
更重要的是,我所有的實體(Project、Test、TestRun 和 TestDomain)都有 DateTime 屬性,它們似乎在這個問題中發揮了作用。 事實上,如果我將 Test 和 TestRun 中的所有 DateTime 屬性標記為[NotMapped]
(同時將所有代碼保留在 ProjectService 中,如上所示),那么異常就會消失! 如果我只留下一個 DateTime 屬性映射(無論是哪個),則會觸發異常。 但是,它們似乎不會對 TestDomain 和上面的代碼造成任何問題。
這對你們中的任何人有任何意義嗎?
我設法通過完全刪除 IncludeFilter 中的 WHERE 子句來解決這種情況(因為它對我的項目並不重要),但我很高興至少了解正在發生的事情並有解決方案。 :)
我不確定這是否正是問題所在,但IncludeFilter
的目標是生成查詢並在數據庫端進行過濾。
但是,未映射IsArchived
屬性。 這意味着,不可能創建將在數據庫端執行的查詢(由於客戶端評估,在 EF Core 2.x 中可能是可能的)。
確保過濾部分可以全部在數據庫中完成。
直接使用ArchivingDate
屬性看起來是可能的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.