Reputation: 2008
I have 4 queries using EntityFramework that are running on trailer/truck/car/plant that I need to join together before executing due to the volume of results.
All 4 entities inherit from type Asset.
Here is the code I am trying to execute and different variations of code:
var truckModels = await truckService.GetAll();
var trailerModels = await trailerService.GetAll();
var companyCarModels = await companyCarService.GetAll();
var plantModels = await plantService.GetAll();
Without anything:
assetModels = truckModels.Cast<Asset>()
.Union(trailerModels)
.Union(companyCarModels)
.Union(plantModels);
With Cast:
assetModels = truckModels.Cast<Asset>()
.Union(trailerModels.Cast<Asset>())
.Union(companyCarModels.Cast<Asset>())
.Union(plantModels.Cast<Asset>());
With AsEnumerable:
assetModels = truckModels.Cast<Asset>()
.Union(trailerModels.AsEnumerable())
.Union(companyCarModels.AsEnumerable())
.Union(plantModels.AsEnumerable());
With Cast and AsEnumerable:
assetModels = truckModels.Cast<Asset>()
.Union(trailerModels.Cast<Asset>().AsEnumerable())
.Union(companyCarModels.Cast<Asset>().AsEnumerable())
.Union(plantModels.Cast<Asset>().AsEnumerable());
However I am getting the following error on all variations:
"This method supports the LINQ to Entities infrastructure and is not intended to be used directly from your code."
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
Any ideas? I thought that you could merge IQueryable...
Upvotes: 1
Views: 314
Reputation: 15772
What is .GetAll()
. It looks to me that you have an unexpected Closure that can't be converted into an EntityFramework operation.
EntityFramework does not know what TruckService
nor TrailerService
is.
If you decompose your Linq Expression, you will find you have an element like
Expression.Lambda(
methodinfo(TruckService.GetAll)
Expression.Parameter(typeof(TruckService))
)
Entity Framework doesn't know that it should reduce that into
Expression.Lambda(
Expression.Call(
methodInfo(DbContext.DbSet<Truck>),
Expression.Parameter(typeof(AssetDbContext))
)
)
You have a few options here.
However it isn't obvious that the DbContext in each AssetService is the same DbContext, which is required for it to partake in the same query.
Upvotes: 1