簡體   English   中英

在具有 DateTime 屬性的實體上使用 IncludeFilter 時出現 InvalidCastException”

[英]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, Func 3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable 1.Enumerator.MoveNext() 在 System.Linq.Lookup 2.CreateForJoin( 2.CreateForJoin(IEnumerable 1 source, Func 2 keySelector, IEqualityComparer 1 2 keySelector, IEqualityComparer ) at System.Linq.Enumerable.Joinable.Joinable. TOuter,TInner,TKey,TResult](IEnumerable 1 outer, IEnumerable 2 outerKeySelector, Func 1 outer, IEnumerable 1 inner, Func 2 outerKeySelector, Func 2 innerKeySelector, Func 3 resultSelector, IEqualityComparer 1 comparer)+MoveNext() at System.Linq.Enum erable.GroupJoinIterator[TOuter,TInner,TKey,TResult](IEnumerable 1 outer, IEnumerable 1 內,Func 2 outerKeySelector, Func 1 outer, IEnumerable2 outerKeySelector, Func 2 內2 outerKeySelector, Func選擇器,Func 3 resultSelector, IEqualityComparer 1 比較器)+MoveNext() 在 System.Linq.Enumerable[。 TSource,TCollection,TResult](IEnumerable 1 source, Func 2 collectionSelector, Func 3 resultSelector)+MoveNext() at System.Linq.Enumerable.SelectEnumerableIterator 2.MoveNext() 在 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() 在 Z.EntityFramework.Plus.QueryFuture 1.SetResult(IEnumerator 1 enumerator) 在 Z.EntityFramework.Plus.QueryFutureEnumerable 1.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.QueryIncludeFilterProvider 1.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM