对具有 DateTime 属性的实体使用包含筛选器时无效的强制转换异常"



我遇到了一个我不理解的InvalidCastException,它特别与Entity Framework Plus库及其IncludeFilter扩展方法有关。

总之,我有三个实体:Project、Test和TestRun:-每个项目都有一组测试;-每个测试都有一个TestRun集合。我有一个ProjectService类,它实现了一个从数据库中检索项目的方法,并提供了选择所需include的选项。以下是该方法的代码(我将其分解为仍然产生相同异常的最小代码段,再加上另一个可进行比较的代码段(:

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(闭包,DbDataReader(位于Microsoft.EntityFrameworkCore.Storage.Interal.TypedRelationValueBufferFactory.Create(DbDataReader dataReader(在Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func3操作中,Func3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.MoveNext((在System.Linq.Lookup2.CreateForJoin(IEnumerable1源,Func2 keySelector, IEqualityComparer1比较器(在System.Linq.Enumerable.JoinTerator[TOuter,TInner,TKey,TResult](IEnumerable1 outer, IEnumerable1 inner,Func2 outerKeySelector, Func2 innerKeySelector,Func3 resultSelector, IEqualityComparer1 comparer(+MoveNext((在System.Linq.Enumerable.GroupJoinTerator[TOuter,TInner,TKey,TResult](IEnumerable1 outer, IEnumerable1 inner,Func2 outerKeySelector, Func2 innerKeySelector,Func3 resultSelector, IEqualityComparer1 comparer(+MoveNext((在System.Linq.Enumerable.SelectManyTerator[TSource,TCollection,TResult](IEnumerable1 source, Func2 collectionSelector,Func3 resultSelector)+MoveNext() at System.Linq.Enumerable.SelectEnumerableIterator2.MoveNext((位于Microsoft.EntityFrameworkCore.Query.Interal.LinqOperatorProvider_TrackEntities[TOut,TIn](IEnumerable1 results, QueryContext queryContext, IList1 entityTrackingInfos,IList1 entityAccessors)+MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.MoveNext((在Z.EntityFramework.Plus.QueryFutureEnumerable1.SetResult(IEnumerator1枚举器(在Z.EntityFramework.Plus.QueryFutureEnumerable1.SetResult(DbDataReader reader) at Z.EntityFramework.Plus.QueryFutureBatch.ExecuteQueries() at Z.EntityFramework.Plus.QueryFutureValue1.get_Value((在Z.EntityFramework.Plus.QueryIncludeFilterProvider1.Execute[TResult](Expression expression) at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable1源,表达式`1谓词(在Treesse.Service.Impl.ProjectService.Get(Int32项目ID,ProjectIncludeOptions包括在内(

最让我困惑的是,当我使用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属性似乎是可能的。

最新更新