Linq strangeness - linq

I was receiving repeating rows from this linq query:
public static Func<DataContext, string, IQueryable<Building>>
GearFilteredBuildings =
CompiledQuery.Compile((DataContext db, string filter) =>
from b in db.Building
join r in db.Router on b equals r.Building
orderby !b.Active
where filter.Length == 5 && r.Name.Substring(1, 5).ToLower() == filter
|| filter.Substring(0, 3) == r.Name.Substring(3, 3).ToLower()
select b);
After some fiddling, I got the distinct Buildings with this:
public static Func<DataContext, string, IQueryable<Building>>
GearFilteredBuildings =
CompiledQuery.Compile((DataContext db, string filter) =>
(from b in db.Building
join r in db.Router on b equals r.Building
orderby !b.Active
where filter.Length == 5 && r.Name.Substring(1, 5).ToLower() == filter
|| filter.Substring(0, 3) == r.Name.Substring(3, 3).ToLower()
group b by b.Id into g
select g) as IQueryable<Building>);
Is this an acceptable solution? How else might this be done?

Not sure (couldn't test it IDE) but select...join...lalala can replaced with Linq-Chain syntax:
db.Routers
.Where(r => filter.Length == 5 && r.Name.Substring(1, 5).ToLower() == filter || filter.Substring(0, 3) == r.Name.Substring(3, 3).ToLower())
.GroupBy(r => r.Building)
.Select(g => g.Key)
.OrderBy(b => !b.Active)
Also: as I can see no joins are really requred in your query, as you have navigation properties (r.Building)in your model.
Or another approach could be used, select all needed buildings, and use .Distinct() afterwards:
db.Routers
.Where (r => filter.Length == 5 && r.Name.Substring(1, 5).ToLower() == filter || filter.Substring(0, 3) == r.Name.Substring(3, 3).ToLower())
.Select(r => r.Building)
.Distinct()
.OrderBy(b => !b.Active)

Related

Single link query where clause to take only `n` of each type from a single model/table

Having a table Entities with a column type (between other columns) how can I select only n entities from type A and m entities from type b in a single linq query where clause? Is it possible?
I am looking for something like this:
var x = from s in db.Entities
where s.type == `A` && (????) < n
|| s.type == `B` && (????) < m
select s
Current solution with combined queries:
var x = entities.Where(e => e.type == `A`).Take(n).Union(
entities.Where(e => e.type == `B`).Take(m));
You could use GroupBy:
var x = db.Entities.GroupBy(x => x.type)
.Where(g => g.Key == "A" || g.Key == "B")
.SelectMany(g => g.Key == "A" ? g.Take(n) : g.Take(m));
But I don't know why you don't like your Union-based solution - it should result in just one query sent to the database anyway.

Get Maximum Value from multiple rows of multiple columns using LINQ?

I'm using LINQPad to evaluate my linq query. My query goes like this:
from o in MyTableFirst
join p in MyTableSecond on o.TheName equals p.TheName
where p.TheName == "CBA-123" && !p.Removed &&
(o.ReturnPeriod ==100 || o.ReturnPeriod ==10)
select new {
HMax1 = o.MaxValue1,
HMax2 = o.MaxValue2,
HMax3 = o.MaxValue3
}
This query can return 0 or some number of rows.
In LINQPad, it return me something like this:
HMax1 HMax2 HMax3
21.1 null 22.5
null 24.6 11.5
Now, how am I going to get the Maximum value out for these return rows & columns?
I'm expecting return of 24.6.Thank You
How about this:
(from o in db.MyTableFirsts
join p in db.MyTableSeconds on o.TheName equals p.TheName
where p.TheName == "CBA-123" && !p.Removed &&
(o.ReturnPeriod == 100 || o.ReturnPeriod == 10)
select new
{
Maximum = Math.Max(
Math.Max((float)(o.MaxValue1 ?? 0), (float)(o.MaxValue2 ?? 0)),
(float)(o.MaxValue3 ?? 0)
)
}).OrderByDescending(o => o.Maximum).FirstOrDefault();
Or instead of .OrderByDescending(o => o.Maximum).FirstOrDefault(), you can use .Max(o => o)
Try this:
(
from o in MyTableFirst
join p in MyTableSecond on o.TheName equals p.TheName
where p.TheName == "CBA-123" && !p.Removed &&
(o.Level ==100 || o.Level ==10)
//combine all of the numbers into one list
let listOfNumbers = new List<double?>{o.MaxValue1,o.MaxValue2,o.MaxValue3}
//select the list
select listOfNumbers
)
.SelectMany(c => c) //combine all the lists into one big list
.Max(c => c) //take the highst number

How to get row count 3 table join and lambda expressions?

I'm trying to get a row count for reports that a user has that match a particular channelId. I've tried using lambda expressions without any luck.
int count =
_reportsRepository.
GetMany(r => r.UserId == user.Id &&
(r.Charts.Any(cr => cr.Channels.Any(ch => ch.Id == channel.Id))).Any()).Count();
What about
int count = _reportsRepository.Where(
r => r.UserId == user.Id &&
r.User.Channels.Any(c => c.Id == channel.Id)).Count();

Convert Linq Query Expression to Method Syntax equivalent

I use LINQ, C#, EF4.
I have this query expression in Linq. I need to convert in a equivalent in Method Syntax but I have some doubt on the struction. Could you provide me a good example. Thanks for your help.
var myContentsForAuthor = from c in context.CmsContents
join a in context.CmsAuthors on c.AuthorId equals a.AuthorId
join u in context.aspnet_Users on a.UserId equals u.UserId
orderby c.Title ascending
where u.UserId == myUserGuid && c.IsDeleted == false && c.Title.Contains(nameSearchString)
select c;
Well, this gets complicated because of the transparent identifiers, but something like:
var myContentsForAuthor = context.CmsContents
.Join(context.CmsAuthors,
c => c.AuthorId
a => a.AuthorId,
(c, a) => new { c, a })
.Join(context.aspnet_Users,
z => z.a.UserId,
u => u.UserId,
(z, u) => new { z, u })
.OrderBy(zz => zz.z.c.Title)
.Where(zz => zz.u.UserId == myUserGuid &&
zz.z.c.IsDeleted == false &&
zz.z.c.Title.Contains(nameSearch))
.Select(zz => zz.z.c);

How do I set conditions from multiple tables in my LINQ query?

In the query below, I want to return people that meet multiple conditions. Some of the conditions apply to fields in the table containing the people to be returned. The other condition is applied to a different table (EmailAddresses) linked to the main table (People) via PersonId.
var t = People.Where(x =>
x.Type == 102 &&
x.FirstName == "Bob" &&
x.LastName == "Williams" &&
x.EmailAddresses.Where (ea=> ea.EmailAddress
== "bob.williams#acme.org")
)
.Select(x => x.PersonId)
How do I do this?
Do understand this right, at least one of them should have that adress? If yes, use the Any method:
var t = People.Where(x =>
x.Type == 102 &&
x.FirstName == "Bob" &&
x.LastName == "Williams" &&
x.EmailAddresses.Any(ea=> ea.EmailAddress
== "bob.williams#acme.org")
)
.Select(x => x.PersonId)
Any returns true if at least one of the elements of the IQueryable<T> fulfills the predicate.
I think you could do it with a join, something like this...
var t = from p in People
join e in EmailAddress on p.PersonId equals e.PersonId into pe
from a in pe.DefaultIfEmpty
where p.Type == 102 &&
p.FirstName == "Bob" &&
p.LastName == "Williams" &&
a.EmailAddress == "bob.williams#acme.org"
select p.PersonId

Resources