【问题标题】:Merging Two IQueryable results returning error合并两个 IQueryable 结果返回错误
【发布时间】:2019-10-20 22:21:27
【问题描述】:

我有 4 个使用 EntityFramework 的查询在拖车/卡车/汽车/工厂上运行,由于结果量大,我需要在执行之前将它们连接在一起。

所有 4 个实体都继承自 Asset 类型。

这是我尝试执行的代码和不同的代码变体:

 var truckModels = await truckService.GetAll();
 var trailerModels = await trailerService.GetAll();
 var companyCarModels = await companyCarService.GetAll();
 var plantModels = await plantService.GetAll();

什么都没有:

 assetModels = truckModels.Cast<Asset>()
 .Union(trailerModels)
 .Union(companyCarModels)
 .Union(plantModels);

有演员表:

 assetModels = truckModels.Cast<Asset>()
 .Union(trailerModels.Cast<Asset>())
 .Union(companyCarModels.Cast<Asset>())
 .Union(plantModels.Cast<Asset>());

使用 AsEnumerable:

 assetModels = truckModels.Cast<Asset>()
 .Union(trailerModels.AsEnumerable())
 .Union(companyCarModels.AsEnumerable())
 .Union(plantModels.AsEnumerable());

使用 Cast 和 AsEnumerable:

 assetModels = truckModels.Cast<Asset>()
 .Union(trailerModels.Cast<Asset>().AsEnumerable())
 .Union(companyCarModels.Cast<Asset>().AsEnumerable())
 .Union(plantModels.Cast<Asset>().AsEnumerable());

但是,我在所有变体中都收到以下错误:

“此方法支持 LINQ to Entities 基础架构,不打算直接从您的代码中使用。”

at System.Data.Entity.Core.Objects.ObjectQuery`1.MergeAs(MergeOption mergeOption)
at lambda_method(Closure )
at System.Linq.EnumerableExecutor`1.Execute()
at System.Linq.EnumerableQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression)
at Kendo.Mvc.Extensions.QueryableExtensions.Count(IQueryable source)
at Kendo.Mvc.Extensions.QueryableExtensions.CreateDataSourceResult[TModel,TResult](IQueryable queryable, DataSourceRequest request, ModelStateDictionary modelState, Func`2 selector)
at Kendo.Mvc.Extensions.QueryableExtensions.<>c__DisplayClass10.<ToDataSourceResultAsync>b__f()
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Viper.Web.Areas.Assets.Controllers.AllController.<GetAssets>d__7.MoveNext() in C:\Repositories\ViperRepo\Viper\Viper.Web\Areas\Assets\Controllers\AllController.cs:line 90

有什么想法吗?我以为你可以合并 IQueryable...

【问题讨论】:

  • 不太确定这里发生了什么,但是如果您的所有可查询对象都属于同一类型,那么查询不能一次性完成而不是将 4 个合并在一起吗?
  • 如果你这样做 AsEnumerable() 为什么你会得到一个 LINQ to Entities 异常......你到底从哪里得到这个异常?
  • 实体的类型不同,但都继承自 Asset。尝试评估资产模型时出现异常
  • 你能发布完整的堆栈跟踪吗?
  • 我认为您需要像使用 truckModels 一样将它们全部转换为 Asset。虽然是疯狂的猜测。

标签: c# performance entity-framework linq iqueryable


【解决方案1】:

.GetAll() 是什么。在我看来,您有一个无法转换为 EntityFramework 操作的意外闭包。

EntityFramework 不知道 TruckServiceTrailerService 是什么。

如果你分解你的 Linq 表达式,你会发现你有一个类似的元素

Expression.Lambda(
       methodinfo(TruckService.GetAll)
       Expression.Parameter(typeof(TruckService))
)

实体框架不知道它应该将其简化为

Expression.Lambda(
       Expression.Call(
            methodInfo(DbContext.DbSet<Truck>),
            Expression.Parameter(typeof(AssetDbContext))
       )
)

这里有几个选项。

  1. 直接使用 DbContext 的实例
  2. 构造一个 ExpressionVisitor 来重写表达式树以进行上述转换

但是每个 AssetService 中的 DbContext 是否是同一个 DbContext 并不明显,这是它参与同一个查询所必需的。

【讨论】:

    猜你喜欢
    • 2012-01-09
    • 1970-01-01
    • 2011-06-21
    • 2016-11-30
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    相关资源
    最近更新 更多