Linq - where inside include - c#

I know that this won't work as written, but I'm struggling to see the right answer, and this non-functional code hopefully illustrates what I'm trying to achieve:
var defaults = _cilQueryContext.DefaultCharges
.Where(dc => dc.ChargingSchedule_RowId == cs.RowId);
List<DevelopmentType> devTypes =
defaults.Select(dc => dc.DevelopmentType)
.Include(d => d.DefaultCharges)
.Include(d => d.OverrideCharges.Where(oc => oc.ChargingSchedule_RowId == cs.RowId))
.Include(d => d.OverrideCharges.Select(o => o.Zone))
.ToList();
Essentially, I had presumed this required a join, but seeing as I'm trying to select a parent object containing two related types of children, I can't see what would go in the join's "select new" clause.

As far as I am aware Include does not support this type of sub-querying. Your best option is to use projection e.g.
List<DevelopmentType> devTypes =
defaults.Include(x => x.DefaultCharges)
.Include(x => x.OverrideCharges)
.Select(x => new {
DevType = x.DevelopmentType,
Zones = x.OverrideCharges.Where(oc => oc.ChargingSchedule_RowId == cs.RowId)
.Select(oc => oc.Zone).ToList()
})
.Select(x => x.DevType)
.ToList();

Related

Use multiple include and then include in EF query C#

I tried this code:
var result = _repository.Entity
.Include(x => x.table1)
.Include(x => x.table2).ThenInclude(x => x.table3).ThenInclude(x => x.table4)
.Where(x => x.table1.Id == 10)
I want to achieve like below which is not working:
var result = _repository.Entity
.Include(x => x.table1).select(new table1{..})
.Include(x => x.table2).ThenInclude(x => x.table3).ThenInclude(x => x.table4)
.Where(x => x.table1.Id == 10)
In this query, I want to use select on table1 i.e. to select on few columns say id, name.
I am trying but I use select right after the .Include(x => x.table1).select(....) then I am unable to use .Include for other tables.
I am not sure how to achieve this with join conditions; I tried but not able to achieve this, a small idea to resolve this will be helpful to proceed further.

NHibernate: Could not resolve property error

I am trying to do a query like:
var a = session.QueryOver<Site>()
.SelectList(
x => x.Select(p => p.SiteName)
.Select(p => p.SiteId).Select(p => p.RegionLocation.City))
.List<object[]>();
but I get the error
could not resolve property: RegionLocation.City of: Entities.Site
The property exists and I can retrieve it using LINQ but QueryOver does not work. What am I doing wrong ?
As far as i remember, with QueryOver, you have to join all entities in the association in order to be able to access it's properties.
This means you ought to do something like:
(notice the .JoinQueryOver)
var a = session.QueryOver<Site>()
.JoinQueryOver(s => s.RegionLocation)
.SelectList(
x => x.Select(p => p.SiteName)
.Select(p => p.SiteId)
.Select(p => p.RegionLocation.City))
.List<object[]>();
Or maybe this will work:
RegionLocation regionLocationAlias = null;
var a = session.QueryOver<Site>()
.JoinAlias(s => s.RegionLocation, () => regionLocationAlias)
.SelectList(
x => x.Select(p => p.SiteName)
.Select(p => p.SiteId)
.Select(() => regionLocationAlias.City))
.List<object[]>();
Also you might want to have a look at https://github.com/davybrion/NHibernateWorkshop/tree/master/NHibernateWorkshop
There's lots of great examples!
Specifically for your problem, have a look at: https://github.com/davybrion/NHibernateWorkshop/blob/master/NHibernateWorkshop/Querying/QueryOver/Projecting.cs

LINQ Grouping by ParentId

I have a seemingly simple task that I am having far more trouble than I care to admit doing. I have a hierarchical table that I need to query and display the results grouped by the parent with associated children.
My current LINQ query:
var quests = Questions.Include(q => q.Question2)
.Include(q => q.Sections)
.Include(q => q.QuestionType)
.Include(q => q.AnswerOptions)
.Where(sq => sq.Sections.Any(s => s.SectionId == sectionId))
.OrderBy(q=> q.QuestionId).ThenBy(q => q.ParentQuestionId);
This produces a result set of:
What I want to produce is:
My Question is simply, how can I get the desired results using Lambda syntax.
Update based on Servys' comment.
First line is to make sure all related questions are grouped together.
Second line is to make sure parent question is first.
Third line is to order properly
.OrderBy(q => q.ParentQuestionId == null ? q.QuestionId : q.ParentQuestionId)
.ThenBy(q => q.ParentQuestionId == null ? 0 : 1)
.ThenBy(q => q.DisplayOrder);
So it seems what you're really trying to create here is a tree based structure in which, at the top level, you have all questions with no parent, and then as "child" nodes all questions that have that as a parent.
var questions = GetAllQuestions();//here is where you can put your includes, etc.
var query = questions.Where(q => q.ParentQuestionId != null)
.GroupBy(q => q.ParentQuestionId)
.Select(group => new
{
Parent = questions.First(q => q.QuestionId == group.Key),
Children = group.OrderBy(q => q.DisplayOrder),
})
.OrderBy(group => group.Parent.DisplayOrder);
.OrderBy(x => (x.ParentQuestionId==null?x.QuestionId:x.ParentQuestionId.Value));

Linq, unable to list only distinct results

I have three tables, car_type, car_manufacturer and car_model. When the user click on the particular vehicle type they want to browse, I'd like to show them a list of available manufacturers. The problem is the list of manufacturers is not distinct or unique. So if my db has three models from Mazda, Mazda will show up on the list 3 times. This is my controller:
public ActionResult Browse(string click_string)
{
var x = carDB.Models
.Include(b => b.Manufacturer)
.Include(a => a.VehicleType)
.Where(a => a.VehicleType.TypeName == click_string);
return View(x.ToList());
}
How can I write this to remove redundant listings? This is all new to me, so go easy on me.
You have to query for Manufacturers, not for Vehicles:
var x = carDB.Models.Where(a => a.VehicleType.TypeName == click_string)
.Select(a => a.Manufacturer)
.Distinct();
It usually works well to try and avoid Distinct altogether. You want manufacturers? Get manufacturers. And determine from there which ones you need: the ones that produce models that have click_string in their type name:
carDB.Manufacturers.Where(manufacturer => manufacturer.Models
.Any(model => model.VehicleType.TypeName == click_string))
You may want to include Models and/or VehicleType, that depends on what you want to show in the view.
First try doing a .Distinct() at the end of the query, if it does not work you might need to provide a custom comparer for the .Distinct()
You should be able to use .Distinct to return the distinct elements.
var x = carDB.Models
.Include(b => b.Manufacturer)
.Include(a => a.VehicleType)
.Where(a => a.VehicleType.TypeName == click_string)
.Distinct();
add distinct
var x = carDB.Models
.Include(b => b.Manufacturer)
.Include(a => a.VehicleType)
.Where(a => a.VehicleType.TypeName == click_string)
.Select(y => y)
.Distinct();
The .Select() might be a bit verbose but without trying it in my visual studio i put it in there for saftey

Subquery parent id in NHibernate QueryOver

I'm trying to understand how this may work.
What I would have is to have all Trees from a given list of IDs that has not rotten apples.
Looks easy but I'm fresh of NHibernate, not so good in SQL and as you can see I'm stuck.
I wrote this code down here:
Tree treeitem = null;
QueryOver<Apple> qapple = QueryOver.Of<Apple>()
.Where(x => (!x.IsRotten))
.And(Restrictions.IdEq(Projections.Property<Tree>(y => y.Id)))
// Or this one...
//.And(Restrictions.EqProperty(
// Projections.Property<Apple>(y => y.Tree.Id),
// Projections.Property<Tree>(y => y.Id)))
.Select(x => x.Id);
return this.NHibernateSession.QueryOver<Tree>()
.Where(x => x.Id.IsIn(ListOfTreeId))
.WithSubquery.WhereExists<Apple>(qapple)
.SelectList(list => list
.Select(z => z.Id).WithAlias(() => treeitem.Id)
.Select(z => z.Name).WithAlias(() => treeitem.Name)
.Select(z => z.Type).WithAlias(() => critem.Type)
.TransformUsing(Transformers.AliasToBean<Tree>())
.List<T>();
And the pseudo SQL I get is something like this:
SELECT id, name, type FROM trees WHERE id IN (1, 2, 3)
AND EXIST(SELECT id FROM apples WHERE NOT rotten AND apples.idtree = apples.id)
As you can see there's a problem with the subquery that use the same table Id instead of something like that:
EXIST(SELECT id FROM apples WHERE NOT rotten AND apples.idtree = tree.id)
I'm bit lost actually. Maybe there's another way to build this up.
Any help is welcome, thanks.
Im not sure why you are using resulttransformer when the return type is the same as the query type
return NHibernateSession.QueryOver<Tree>()
.Where(t => t.Id.IsIn(ListOfTreeId))
.JoinQueryOver<Apple>(t => t.Apples)
.Where(a => !a.IsRotten)
.List();
Update: the Compiler chooses ICollection<Apple> while it really should choose Apple therefor specify the generic argument in JoinQueryOver explicitly
Update2: to get them unique
opt 1)
...
.SetResultTransformer(Transformers.DistinctRootEntity());
.List();
opt 2)
Tree treeAlias = null;
var nonRottenApples = QueryOver.Of<Apple>()
.Where(a => !a.IsRotten)
.Where(a => a.Tree.Id == treeAlias.Id)
.Select(x => x.Id); <- optional
return NHibernateSession.QueryOver(() => treeAlias)
.Where(t => t.Id.IsIn(ListOfTreeId))
.WithSubquery.WhereExists(nonRottenApples)
.List();

Categories