I'm trying to group Reports by Type and return the most recent Created date for each Report Type, using LINQ to Entities. I did my research and read lots of questions and most of them are solved using a similar query than mine:
var query = ctx.DataWorkspace.ApplicationData.Reports
.GroupBy(i => i.ReportType)
.Select(i => new { name = i.Key, y = i.Max(h => h.DateCreated) });
But I get this error:
A query cannot return non-Entity types that contain embedded entities
What am I doing wrong? Is it because it's LINQ-to-Entities?
Error message is quite descriptive. Your anonymous type contains a property which is typed as an entity (name = i.Key part). You can't do that, because LINQ to Entities would not be able to track changes to these entities.
You can take just some of the properties from ReportType instead of entire entity:
var query = ctx.DataWorkspace.ApplicationData.Reports
.GroupBy(i => i.ReportType)
.Select(i => new { name = i.Key.Name, y = i.Max(h => h.DateCreated) });
i.Key.Name is just an example. Your entity probably has different property/properties you care about.
Related
I'm trying to get specific columns from a context with several includes, but when I try:
Context.Include(i => i.c)
.Include(i => i.l).Select(s=> new LocationCatalog { Name = s.Name})
.Include(i => i.p)
.Include(i => i.li)
.Include(i => i.pcl)
VS throws an error after the select.
How can I achieve this? I want to specify the columns for each include.
The error says that for example: i.p doesn't contains definition for i.l
That's not possible with Entity Framework. You either include the entire table (with Include, as you are doing) or you don't include it at all.
If you want to load only specific columns, you can do this, but see how it's a manual process:
Context
.Select(i => new YourType
{
c = i.l,
l = i.l,
x = new X
{
a = i.x.a // only the properties you want here
}
...
});
The moment you use Select, Include is completely ignored, so you cannot use both.
I've got a table
Application
ApplicationID,
NAme
ApplicationSteps
AplicationStepID,
AplicationID,
StepID
ApplicationStepCriterias
ApplicationStepID,
CriteriaID
So I've got one SelectedCriteriaID - a user choose from a dropdown one criteria and he wants all the applications which has this SelectedCriteriaID in the table ApplicationStepCriterias
I tried
var ds = context.Applications
.Where(a => a.ApplicationSteps
.Select(x=>x.ApplicationStepCriterias
.Select(t=>t.CriteriaId))
.Contains(SelectesdCriteria));
But as I have as result IEnumerable<IEnumerable<int>> I cannot use Contains
Just I get a list of all the CriteriaIds for each ApplicationStep(also a sequence). Just I cannot think of way to get in one list all the CriteriIds.
First, let me try to get the names right. This is not a pure many-to-many association, because the junction class is part of the class model. It is what I unofficially call a 1-n-1 association. So you have
Application -< ApplicationSteps >- ApplicationStepCriterias
I'd strongly recommend to use singular names for your classes ...
Application -< ApplicationStep >- ApplicationStepCriterion
... so you can use plural for collection property names without getting confused.
If I'm right so far, you query should be
context.Applications
.Where(a => a.ApplicationSteps
.Any(x => selectedCriteria
.Contains(x.ApplicationStepCriterion.CriteriaId));
(and I'd also prefer CriterionId, probably referring to a Criterion class)
You may try something like this:
var applicationStepIds = context.ApplicationStepCriterias
.Where(i => i.CriteriaID == selectedCriteria)
.Select(i => i.ApplicationStepID)
.Distinct();
var applicationIds = context.ApplicationSteps
.Where(i => applicationStepIds.Contains(i.AplicationStepID))
.Select(i => i.AplicationID)
.Distinct();
var result = context.Applications.Where(i => applicationIds.Contains(i.ApplicationId));
I got the following error message from nhibernate:
{"not an association: ID"}
Model.Order orderAlias = null;
Model.Unit unitAlias = null;
query to reproduce:
var query = m_hibernateSession.QueryOver<Model.Order>(() => orderAlias)
.JoinAlias(() => orderAlias.ID, () => unitAlias, JoinType.InnerJoin)
.TransformUsing(Transformers.DistinctRootEntity)
.OrderBy(x => x.PONumber).Desc.Take(5);
(for DB model look also here: nhibernate criteria for selecting from different tables)
What does this mean and how can I correctly retrieve my result list?
Thx
In Model.Order class, ID should be of type Model.Unit.
Make sure you have classes for both Model.Order and Model.Unit
I have 3 entities: Banners, Packs and Files.
One Banner has many packs and one pack has many files.
I need to get all the files ids for all banners. I tried the following:
IList<BannerModel> banners = context.Banners
.OrderBy(x => Guid.NewGuid())
.Take(count)
.Select(x =>
new BannerModel {
Images = x.Packs.SelectMany(p => p.Files.Select(f => f.Id)).ToList()
}).ToList();
However, I am getting an error on the Files id selecting:
System.NotSupportedException: LINQ to Entities does not recognize the
method 'System.Collections.Generic.List1[System.Int32]
ToList[Int32](System.Collections.Generic.IEnumerable1[System.Int32])'
method, and this method cannot be translated into a store expression.
at
System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter
parent, MethodCallExpression call) at ...
Any idea of what might be wrong?
NOTE: I have Lazy Loading disabled.
var allFileIDs = context.Banners.SelectMany(b =>
b.Packs.SelectMany(p => p.Files.Select(f => f.ID)))
.ToList();
Resulting SQL will look like:
SELECT [t2].[ID]
FROM [Banners] AS [t0], [Packs] AS [t1], [Files] AS [t2]
WHERE ([t1].[BannerID] = [t0].[ID]) AND ([t2].[PackID] = [t1].[ID])
No lazy-loading, single query.
Misunderstood your question about getting all file ids. If you need to project each banner to BannerModel:
context.Banners.Select(b => new BannerModel {
Images = b.Packs.SelectMany(p => p.Files.Select(f => f.ID))
}).ToList();
You see exception, because you have ToList() in expression, which cannot be converted into SQL. Change BannerModel.Images to be of type IEnumerable<int> instead of List<int>, and remove ToList() call from select statement.
One more option if you don't want to change type of BannerModel.Images:
context.Banners.Select(b => b.Packs.SelectMany(p => p.Files.Select(f => f.ID)))
.ToList() // brings next projection into memory
.Select(ids => new BannerModel { Images = ids.ToList() })
.ToList();
I have a query over a single entity (with some navigation properties) and need to project them into a model for consumption by API clients. It looks basically like this:
repository.CreateQuery<Reviews>()
.Where(/* criteria */)
.Select(m => new
{
ID = m.ID,
Reviewers = m.IsAnonymous
? m.Reviewers.Take(1).Select(r => new { Name = "Anonymous" })
: m.Reviewers.Select(r => new { Name = r.Name })
})
LINQ to Entities fails to execute this at runtime. In the Visual Studio debugger, the exception message is "Specified method is not supported". In LinqPad, the inner exception is "The nested query is not supported. Operation1='Case' Operations2='Collect'".
Any ideas how to work around this? I'd rather not force the query to execute to get the objects in memory because the point of this conditional query is to solve a performance issue, so as far as I can tell I really need to solve this within the scope of the L2E query.
Update: the projected types aren't anonymous in my real application. I just used anonymous ones here because it was convenient to contrive the example. In similar fashion, the real queries involve a number of additional properties which mean a great deal more data coming from the mapped tables.
You can use union to do what you want:
var query1 = repository.CreateQuery<Reviews>()
.Where(/* criteria */);
var queryAnonimous = query1.Where(m=>m.IsAnonymous)
.Select(m => new
{
ID = m.ID,
Reviewers = m.Reviewers.Take(1).Select(r => new { Name = "Anonymous" })
})
var queryNotAnonymous = query1.Where(m=>!m.IsAnonymous)
.Select(m => new
{
ID = m.ID,
Reviewers = m.Reviewers.Select(r => new { Name = r.Name })
})
var unionQuery = queryAnonimous.union(queryNotAnonymous);