syntax in LINQ IEnumerable<string> - c#

This is my code that works great:
IPRepository rep = new IPRepository();
var Q = rep.GetIp()
.Where(x => x.CITY == CITY)
.GroupBy(y => o.Fam)
.Select(z => new IpDTO
{
IId = z.Key.Id,
IP = z.Select(x => x.IP).Distinct()
});
IP is IEnumerable<string>
I need to add to this code above a call to a function PAINTIP(ip).
I need to send each one of the elements that will be inside IP to a function PAINTIP(ip).
therefore i need to use some kind of foreach function but i cannot figure out how.

rep.GetIp()
.Where(x => x.CITY == CITY)
.GroupBy(y => o.Fam)
.Select(z => new IpDTO
{
IId = z.Key.Id,
IP = z.Select(x => x.IP).Distinct()
})
.SelectMany(item => item.IP)
.ToList()
.ForEach(PAINTIP)

You can do something like this :
var result = from item in collection
.Where(i => i.condition == value)
.Select(i => new{ Name = i.name, Description = i.Description })
.ToList().ForEach(i => Function(i));
Hope this help !

Very similiar to the answer of this question
LINQ equivalent of foreach for IEnumerable<T>
There is no For Each for an IEnumerable but there is for List
items.ToList().ForEach(i => i.DoStuff());
Edit
I'm not sure you can do it in the way you want to other than this:
ep.GetIp()
.Where(x => x.CITY == CITY)
.GroupBy(y => o.Fam)
.Select(z => new IpDTO
{
IId = z.Key.Id,
IP = z.Select(x => x.IP).Distinct()
})
.ToList().ForEach(IpObj => IpObj.IP.ToList().ForEach(ip => PAINTIP(ip));
This way you get your list of IpDTO objects out first. Then Enumerate over each and then in turn over each IpDTO objects IP IEnumerable. I haven't seen a way to do it where you can Enumerate inside the creation of your IpDTO object. If someone has an example of how to do so I'd like to see to learn myself.

Related

EF Dynamic Field Select using LINQ

I have the following select:
var sortedCodes = Codes
.Where(c => c.Active)
.OrderByDescending(x => x.SortOrder)
.Select(b => new { b.Display, b.NumericCode, b.SortOrder })
.Distinct()
.ToList();
The table Code has many columns such as NumericCode, TextCode, AlphaCode, ThreeCode, FourCode, FiveCode. I am using this table to build selects in my UI. Is there a way I can create some dynamic code so I can pass in the column name to use for the value?
The above select would look like this:
.Select(b => new { b.Display, "TextCode", b.SortOrder })
I was thinking I could use an Expression, but I do not think this is exactly what I need as it is actually printing the lambda as the value.
var arg = Expression.Parameter(typeof(Code), "b");
var body = Expression.Property(arg, valueColumn);
var lambda = Expression.Lambda<Func<Code, string>>(body, arg);
var sortedCodes = Codes
.Where(c => c.Active)
.OrderByDescending(x => x.SortOrder)
.Select(b => new { b.Display, Value=lambda, b.SortOrder })
.Distinct()
.ToList();

Linq Count inside Select, nested, minimizing immediate execution database dependency calls

I have a massive LINQ query that fetches information that looks like this:
In other words, first-level categories, which own second-level categories, which own third level categories. For each category we retrieve the number of listings it contains.
Here is the query:
categories = categoryRepository
.Categories
.Where(x => x.ParentID == null)
.Select(x => new CategoryBrowseIndexViewModel
{
CategoryID = x.CategoryID,
FriendlyName = x.FriendlyName,
RoutingName = x.RoutingName,
ListingCount = listingRepository
.Listings
.Where(y => y.SelectedCategoryOneID == x.CategoryID
&& y.Lister.Status != Subscription.StatusEnum.Cancelled.ToString())
.Count(),
BrowseCategoriesLevelTwoViewModels = categoryRepository
.Categories
.Where(a => a.ParentID == x.CategoryID)
.Select(a => new BrowseCategoriesLevelTwoViewModel
{
CategoryID = a.CategoryID,
FriendlyName = a.FriendlyName,
RoutingName = a.RoutingName,
ParentRoutingName = x.RoutingName,
ListingCount = listingRepository
.Listings
.Where(n => n.SelectedCategoryTwoID == a.CategoryID
&& n.Lister.Status != Subscription.StatusEnum.Cancelled.ToString())
.Count(),
BrowseCategoriesLevelThreeViewModels = categoryRepository
.Categories
.Where(b => b.ParentID == a.CategoryID)
.Select(b => new BrowseCategoriesLevelThreeViewModel
{
CategoryID = b.CategoryID,
FriendlyName = b.FriendlyName,
RoutingName = b.RoutingName,
ParentRoutingName = a.RoutingName,
ParentParentID = x.CategoryID,
ParentParentRoutingName = x.RoutingName,
ListingCount = listingRepository
.Listings
.Where(n => n.SelectedCategoryThreeID == b.CategoryID
&& n.Lister.Status != Subscription.StatusEnum.Cancelled.ToString())
.Count()
})
.Distinct()
.OrderBy(b => b.FriendlyName)
.ToList()
})
.Distinct()
.OrderBy(a => a.FriendlyName)
.ToList()
})
.Distinct()
.OrderBy(x => x.FriendlyName == jobVacanciesFriendlyName)
.ThenBy(x => x.FriendlyName == servicesLabourHireFriendlyName)
.ThenBy(x => x.FriendlyName == goodsEquipmentFriendlyName)
.ToList();
This was fast enough on my dev machine, but alas! Deployed to Azure it's very slow. The reason seems to be that this query is making hundreds of dependency calls to the database, I'm pretty sure because of the immediate execution of the Count statements. Although the app and the database are in the same datacenter, the calls add up in a way they didn't on my dev machine (~40s vs < 1s). So what I'd like to do is send this whole thing off to the database, let it crunch, and get it all back in one hit, if it's possible. How do I do this? Also if I'm approaching this whole thing wrong please tell me. This is the biggest bottleneck in my web app so any help to make it more efficient is appreciated. Thank you! (I'm less concerned about web app memory usage than I am about the cumulative effect of all the database calls.)
This is my suggestion to your massive query.
Don't use ToList() inside the inner queries.
Don't use Count() inside the inner queries.
Try to retrieve all the data once without above IEnumerable operations.In other words fetch the data as IQueryable mode.After loading it in to the App's memory,you can create your data model as you wish.This process will give huge performance boost to your app.So try that and let us know.
Update : about Count()
If you have lot of columns on that list, just fetch a 1 column without Count() using projection.After that you can get the count() on your IEnumerable list.In other words on your app's memory after fetching it from the db.
Here's what I've got so far. It's working really well, but I'm still curious if I can do this in one DB trip, not two. That would seem to be complicated by the fact that each repository has its own DBContext. If you guys have any more thoughts I'd be more than happy to upvote you.
var allCategories = categoryRepository
.Categories
.Select(x => new
{
x.CategoryID,
x.FriendlyName,
x.RoutingName,
x.ParentID
})
.ToList();
var allListings = listingRepository
.Listings
.Where(x => x.Lister.Status != Subscription.StatusEnum.Cancelled.ToString())
.Select(x => new
{
x.SelectedCategoryOneID,
x.SelectedCategoryTwoID,
x.SelectedCategoryThreeID,
})
.ToList();
categories =
allCategories
.Where(x => x.ParentID == null)
.Select(a => new CategoryBrowseIndexViewModel
{
CategoryID = a.CategoryID,
FriendlyName = a.FriendlyName,
RoutingName = a.RoutingName,
ListingCount = allListings
.Where(x => x.SelectedCategoryOneID == a.CategoryID)
.Count(),
BrowseCategoriesLevelTwoViewModels =
allCategories
.Where(x => x.ParentID == a.CategoryID)
.Select(b => new BrowseCategoriesLevelTwoViewModel
{
CategoryID = b.CategoryID,
FriendlyName = b.FriendlyName,
RoutingName = b.RoutingName,
ParentRoutingName = a.RoutingName,
ListingCount = allListings
.Where(x => x.SelectedCategoryTwoID == b.CategoryID)
.Count(),
BrowseCategoriesLevelThreeViewModels =
allCategories
.Where(x => x.ParentID == b.CategoryID)
.Select(c => new BrowseCategoriesLevelThreeViewModel
{
CategoryID = c.CategoryID,
FriendlyName = c.FriendlyName,
RoutingName = c.RoutingName,
ParentRoutingName = b.RoutingName,
ParentParentID = a.CategoryID,
ParentParentRoutingName = a.RoutingName,
ListingCount = allListings
.Where(x => x.SelectedCategoryThreeID == c.CategoryID)
.Count()
})
.OrderBy(x => x.FriendlyName)
})
.OrderBy(x => x.FriendlyName)
})
.OrderBy(x => x.FriendlyName == jobVacanciesFriendlyName)
.ThenBy(x => x.FriendlyName == servicesLabourHireFriendlyName)
.ThenBy(x => x.FriendlyName == goodsEquipmentFriendlyName);

EF6 Condition based on sub child

I have this C# code that works, but I'd like to be able to choose the Agency if a person is in it all in the query. Is there a way to do that all in the query?
var retVal = new List<Agency>();
var items=_db.Agencies
.Include(x => x.AgencyMembers.Select(y => y.Person))
.Where(w => w.NationId == User.NationId).ToList();
foreach (var agency in items)
{
if(agency.AgencyMembers.Any(c=>c.Person.Id==personId))
retVal.Add(agency);
}
return retVal;
You should be able to just add that predicate to your query.
return _db.Agencies
.Include(x => x.AgencyMembers.Select(y => y.Person))
.Where(w => w.NationId == User.NationId)
.Where(agency => agency.AgencyMembers.Any(c=>c.Person.Id==personId))
.ToList();
Depending what navigation properties you have, you may be able to simplify it by starting from the person.
return _db.People
.Single(p => p.Id == personId)
.Agencies
.Where(w => w.NationId == User.NationId)
.ToList();
You can try this:
var items=_db.Agencies
.Include(x => x.AgencyMembers.Select(y => y.Person))
.Where(agency=> agency.NationId == User.NationId && agency.AgencyMembers.Any(c=>c.Person.Id==personId))
.ToList();

Getting no results from simple Query

I've tried the following and it returned me every Tutor
List<Tutor>tutorsList = tutors.ToList();
Furthermore, I tried to select only Tutors with a specific subject (Tutor-Subject is n:n)
Subject subjectEntity = subjects.Where(s => s.Name == input).FirstOrDefault();
List<Tutor>tutorsList = tutors.Where(t => t.Subjects.Contains(subjectEntity)) .ToList();
As a result, my tutorsList is empty, even subjectEntity is correct (I printed it to console).
But when I loop every Tutor and print the Subjects, there is a Tutor with Subject input.
Any ideas?
If you also have id's, you can do the following:
Subject subjectEntity = subjects
.Where(s => s.Name == input)
.FirstOrDefault();
List<Tutor> tutorsList = tutors
.Where(t => t.Subjects
.Select(x => x.SubjectId)
.Contains(subjectEntity.SubjectId)
)
.ToList();
If not, you can try to do it in a single query
List<Tutor> tutorsList = tutors
.Where(t => t.Subjects.Any(x => x.Name == input))
.ToList()
simplify in one line, using Any, when working on an inner collection.
var tutorsList = tutors.Where(t => t.Subjects
.Any(s => s.Name == input)).ToList();
Try below
Subject subjectEntity = subjects.Where(s => s.Name == input).FirstOrDefault();
List<Tutor>tutorsList = tutors.Where(t => t.Subjects.Any(x=>x.UniqueField==subjectEntity.UniqueField)).ToList();

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