Ошибка возврата двух результатов IQueryable - PullRequest
1 голос
/ 05 июня 2019

У меня есть 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);

С Cast:

 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 ...

1 Ответ

1 голос
/ 06 июня 2019

Что такое .GetAll(). Мне кажется, у вас неожиданное закрытие, которое нельзя преобразовать в операцию EntityFramework.

EntityFramework не знает, что такое TruckService или TrailerService.

Если вы разложите свое выражение Linq, вы обнаружите, что у вас есть такой элемент, как

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

Entity Framework не знает, что должно уменьшить это до

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

У вас есть несколько вариантов здесь.

  1. Работа с экземпляром DbContext напрямую
  2. Создайте ExpressionVisitor, чтобы переписать дерево выражений, чтобы преобразование, указанное выше,

Однако не очевидно, что DbContext в каждом AssetService - это один и тот же DbContext, который требуется для того, чтобы он участвовал в том же запросе.

...