Linq to Entities: multiple criteria query for one table - entity-framework

using (WinFileContextContainer c = new WinFileContextContainer())
{
IQueryable<File> dbfiles = (from f in c.File
where //(f.Category.Any((category => category.name == categoryname)) &&
f.alive //&&
//f.description == "" &&
//f.Category.Count == 1)
select f);
// the rest....
}
The query works only as it is now - I left just one criteria (the rest is in comment sections). But I want the other criteria to be taken into account too. I tried with multiple "where"s :D or all the criteria in brackets with one "where", but still no success. I'm kinda new to LINQ so any help is appreciated. Thanks in advance !

Finally got it to work:
IQueryable<File> dbfiles =
c.File.Where(f => f.Category.Any(cat => cat.name == categoryname) &&
f.alive &&
f.description == null &&
f.Category.Count == 1);

Related

How to sort on DB side, if entities are not connected via Navigation (since it's not possible)

I want to have my EfCore query translated into the following SQL query:
select
c.blablabla
from
codes c
left join lookups l on c.codeId = l.entityid and l.languageCode = <variable - language code of current thread> and l.lookuptype = 'CODE'
where
..something..
order by
l.displayname
Note: tables 'codes' and 'lookups' are not connected! 'lookups' contains a lot of different lookup data in different languages!
I am stuck into limitations of EfCore (like 'NavigationExpandingExpressionVisitor' failed). I don't want to make in-memory filtering, it looks silly to me... Am I missing something obvious?
In perspective, I'd like to make universal method to help sort by displayname (or other lookup name) for different kind of entities - not only codes.
Seems like I figured it out. If there's a better approach - please let me know:
protected override IQueryable<FixCode> SortByDisplayName(IQueryable<FixCode> queryable, string languageCode = null)
{
return queryable
.GroupJoin(
DbContext.FixCodeValues.Where(x =>
x.DomainId == CentralToolConsts.Domains.CENTRAL_TOOLS
&& x.CodeName == CentralToolsFieldTypes.CODE_ORIGIN
&& (x.LanguageCode == languageCode || x.LanguageCode == CentralToolsDbLanguageCodes.English)),
//TODO: this will be a 'selector' parameter
code => code.CodeOriginId,
codeOrigin => codeOrigin.StringValue,
(c, co) => new
{
Code = c,
CodeOrigin = co
}
)
.SelectMany(
x => x.CodeOrigin.DefaultIfEmpty(),
(x, codeOrigin) => new { Code = x.Code, CodeOrigin = codeOrigin }
)
.OrderBy(x => x.CodeOrigin.ShortName)
.Select(x => x.Code);
}

Entity Framework check result null

I am using this query:
var result = from r in db.Registrations
join u in db.UserTypes on r.UserTypeId equals u.UserTypeId
where r.Email.ToLower()==model.LoginEmail.ToLower() && r.Password.ToLower() == model.Password.ToLower()
select new { r,u};
Here how can I check that if no record is found? If so, then
if(result == null)
// no record found
else
// record found
You can use Any or Count extension method:
if(!result.Any())
///norecord found
else
//record found
Using Count would be:
if(result.Count()==0)
///norecord found
else
//record found
First what you assign to a result is just IQueryable so it's query and you need to execute it first. So I suggest renaming it to query and then do it like this:
var query= from r in db.Registrations
join u in db.UserTypes on r.UserTypeId equals u.UserTypeId
where r.Email.ToLower()==model.LoginEmail.ToLower() && r.Password.ToLower() == model.Password.ToLower();
select new { r,u};
var result = query.FirstOrDefault(); // gives first result or null
if (result == null) {
// no record
} else {
// record found and is in result
}

LINQ to Entities query to verify all rows exist

I have a need to verify that all the rows in a given set exist in the database and the current user has access to all the rows. I'd like to do this in a single query to the database, something like a .All() query but I can't quite come up with the right syntax (maybe it's not possible).
The iterative version of the code would look like:
bool canAccess;
foreach(var taskId in taskIds)
{
canAccess = await DataContext.WorkTasks.AnyAsync(wt => wt.DealerId == dealerId && wt.Id == taskId);
if(!canAccess) break;
}
I was thinking about something like:
var canAccess = await DataContext.WorkTasks.AllAsync(wt => wt.DealerId == dealerId && taskIds.Contains(wt.Id));
But I don't think that's what I want. Can this be done using LINQ?
Something like this:
var dbCount = await DataContext.WorkTasks.Where(wt => wt.DealerId == dealerId && taskIds.Contains(wt.Id)).Count();
Will send all your IDs to the server and count the matching rows.
To combine into a single query:
var q = DataContext.WorkTasks.Take(0); // setup q to right type
foreach (var taskId in taskIds)
q = q.Concat(DataContext.WorkTasks.Where(wt => wt.Id == taskId && wt.DealerId == dealerId));
var canAccess = (taskIds.Count() == q.Count());

How to write this Query in LINQ

I have one LINQ query with foreach loop. Everything is fine. But it takes more time to get the value. So anybody suggest me how can i do this in LINQ query itself.
Code
NormValue = "";
c = 0;
var NormValuelist = db.BCont.Where(x => x.BId == BId && x.TNo == Tag).ToList();
foreach (var item in NormValuelist)
{
if (c == 0)
NormValue = item.NormValue;
else
NormValue += " " + item.NormValue;
c = 1;
}
Thanks
You can rewrite this query with string.Join to avoid creating multiple string objects in a loop, like this:
string NormValue = string.Join(" ", db.BCont.Where(x => x.BId == BId && x.TNo == Tag));
The number of round-trips to DB will remain the same, but the creation of List<string> and the partially concatenated string objects will be optimized out.
In addition to using String.Join, you could also use Enumerable.Aggregate:
var NormValueList =
db.BCont.Where(x => x.Bid == BId && x.TNo == Tag)
.Select(x => x.NormValue)
.Aggregate((s, x) => s + " " + x);
If you are having large items in "NormValuelist" then it would be better to use StringBuilder instead of string(NormValue)

How can I embed optional Where parameters in a Linq to EF statement?

Let's say we have a description field on my form with optional check boxes. The check boxes represent which fields to search when doing the lookup. Right now I have a matrix of look ups that call their unique version of where clause. It works but I think it smells a bit.
Here is an excerpt
// Look for part numbers decide how many fields to search and use that one.
// 0 0 X
if (!PartOpt[0] && !PartOpt[1] && PartOpt[2])
{
query = query.Where(p => (p.PartNumAlt2.Contains(partSearchRec.inventory.PartNum)));
}
// 0 X 0
if (!PartOpt[0] && PartOpt[1] && !PartOpt[2])
{
query = query.Where(p => (p.PartNumAlt.Contains(partSearchRec.inventory.PartNum)));
}
// 0 X X
if (!PartOpt[0] && PartOpt[1] && PartOpt[2])
{
query = query.Where(p => (p.PartNumAlt.Contains(partSearchRec.inventory.PartNum)
|| p.PartNumAlt2.Contains(partSearchRec.inventory.PartNum)));
}
// X 0 0
if (PartOpt[0] && !PartOpt[1] && !PartOpt[2])
{
query = query.Where(p => (p.PartNum.Contains(partSearchRec.inventory.PartNum)));
}
. . .
This goes on for a while and seems to be prone to coding errors. In each case we are looking for the same information in any of the selected fields. If I was doing this in SQL I could simply build up the WHERE clause as needed.
Once again I rubber ducked my way to an answer. Rather than throw the question away, here is what I came up with. Is it efficient?
if (partSearchRec.optPartNum || partSearchRec.optAltPartNum1 || partSearchRec.optAltPartNum2)
{
query = query.Where(p => (
(partSearchRec.optPartNum && p.PartNum.Contains(partSearchRec.inventory.PartNum))
|| (partSearchRec.optAltPartNum1 && p.PartNumAlt.Contains(partSearchRec.inventory.PartNum))
|| (partSearchRec.optAltPartNum2 && p.PartNumAlt2.Contains(partSearchRec.inventory.PartNum))));
}
Basically if any of the check boxes are set we will execute the query. Each line of the query will be processed only if the check box was checked. If the left side of an AND is false it doesn't process the right.
This is an aera that Delphi's with statement would be handy. I also learned that you can't use an array inside the LINQ statement.