Linq to nhibernate sql 1 = 1 equivalent - linq

I am trying to do a search with LINQ to NHibernate.
I have this code:
from d in rep.QueryAll<Document>()
where
d.Plata != null && d.Contractant != null && d.Stadiu == StadiuDocument.Polita
&& (d.NrPolita.Contains(query) ||
d.Contractant.CodUnic.Contains(query) ||
d.Contractant.Denumire.Contains(query) ||
d.Plata.IdTranzactie.Contains(query)) &&
((TipPolita != null) ? (d.Tip == (TipProdus)TipPolita) : (1 == 1)) &&
((StareDocument != null) ? (d.Stare == (StareDocument)StareDocument) : (1 == 1))
select new
{
The problem is that I have some select inputs that have general values. Something like this:
<select id="tippolita" >
<option value = "-1">Any value</option>
<option value = "1">Value 1</option>
<option value = "2">Value 2</option>
<option value = "3">Value 3</option>
</select>
So when "Any value" is selected the where statement should be true like I wrote here:
((TipPolita != null) ? (d.Tip == (TipProdus)TipPolita) : (1 == 1)) &&
((StareDocument != null) ? (d.Stare == (StareDocument)StareDocument) : (1 == 1))
This is almost the same as what I would write in SQL.
An error occurs inside the Nhibernate source code at line 33 in the file "Linq\NHLinqExpression.cs"
_expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees(expression);
This error actually comes from the re-linq library.
One obvious workaround is to just write 3 if statements and put the appropriate LINQ queries in each of them but that means writing a lot more code.
Is there any way to make this kind of query work without copy-pasting the entire query and modifying just a little of it?
P.S.
This is the inner exception:
InnerException: System.NullReferenceException
Message=Object reference not set to an instance of an object.
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at lambda_method(Closure
)

I would rewrite this:
((TipPolita != null) ? (d.Tip == (TipProdus)TipPolita) : (1 == 1)) &&
((StareDocument != null) ? (d.Stare == (StareDocument)StareDocument) : (1 == 1))
as
(TipPolita == null || d.Tip == (TipProdus)TipPolita) &&
(StareDocument == null || d.Stare == (StareDocument)StareDocument)
I don't know whether it'll work in NHibernate or not, but it's more idiomatic C# at least, so I would expect that it's more likely to be supported.
As an alternative, you could just replace "1 == 1" with "true".

Well, figured out how to do this the proper way
var date = rep.QueryAll<Document>().Where(d => d.Plata != null && d.Contractant != null && d.Stadiu == StadiuDocument.Polita);
if (!string.IsNullOrEmpty(query))
date = date.Where(d => (d.NrPolita.Contains(query) ||
d.Contractant.CodUnic.Contains(query) ||
d.Contractant.Denumire.Contains(query)));
I just move the ifs into the code and build the query(or rather the IQueryable) bit by bit

Related

Is it possible to use Linq with LazyCache

I hope you are well. Is it possible to query the LazyCache cache using Linq?
// Initialize Class
retVal = (ModelXyz)MemoryCache.Default.Where(u => (u.Value is ModelXyz) &&
(u.Value as ModelXyz).Property1 == abc &&
(u.Value as ModelXyz).Property2 == cde &&
(u.Value as ModelXyz).Property3 == true).Select(x => x.Value).FirstOrDefault();

Dynamic Query based on all optional parameters using an OR condition in ef core

I'm not sure if I'm barking up the wrong tree but I wanted to create a function to check if an account exists based on all optional parameters so it can be used to pull data depending on whatever you'd like to check on.
Basically the query should be:
where loginName = p1 or loginName = p2 or loginName = p3 but with the paramters all being optional, however at least one will be provided.
This is what I tried so far:
public async Task<bool> CheckAccountExistsAsync(string loginName = "", string authenticatorId = "", string eId = "")
{
if (string.IsNullOrWhiteSpace(loginName) && string.IsNullOrWhiteSpace(authenticatorId) && string.IsNullOrWhiteSpace(eId))
throw new InvalidOperationException("You must pass at least one parameter");
return await _context.Accounts.AnyAsync(a =>
(string.IsNullOrWhiteSpace(loginName) || a.LoginName == loginName)
|| (string.IsNullOrWhiteSpace(authenticatorId) || a.AuthenticatorId == authenticatorId)
|| (string.IsNullOrWhiteSpace(eId) || a.EmployeeId == eId));
}
Problem with this approach is that if I just pass the loginName, then the query is as follows with the condition completely omitted.:
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [Accounts] AS [a]) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END
I'm sure I'm missing something, is there a better approach?
What you are using is applicable for optional and expressions, e.g.
return await _context.Accounts.AnyAsync(a =>
(string.IsNullOrWhiteSpace(loginName) || a.LoginName == loginName)
&& (string.IsNullOrWhiteSpace(authenticatorId) || a.AuthenticatorId == authenticatorId)
&& (string.IsNullOrWhiteSpace(eId) || a.EmployeeId == eId));
For optional or you have to use optional and sub conditions and add additional check for all optional parameters missing, e.g.
return await _context.Accounts.AnyAsync(a =>
(string.IsNullOrWhiteSpace(loginName)
&& string.IsNullOrWhiteSpace(authenticatorId)
&& string.IsNullOrWhiteSpace(eId))
|| (!string.IsNullOrWhiteSpace(loginName) && a.LoginName == loginName)
|| (!string.IsNullOrWhiteSpace(authenticatorId) && a.AuthenticatorId == authenticatorId)
|| (!string.IsNullOrWhiteSpace(eId) && a.EmployeeId == eId));

Linq Join.Where vs Where.Join performance diff

Is there any difference in performance for linq in following case:
db.Table1.Where(p=>p.Item == 2).Join(db.Table2).Where(pq => q.Item == 3).Join(db.Table3).Where(pqr.r.Item == 3)
vs
db.Table1.Join(db.Table2).Join(db.Table3).Where(pqr => pq.p.Item == 2 && pqr => pq.q.Item == 3 && pqr.r.Item == 3)

Ho to use If condition in LINQ Where clause

Can I use if clause with Linq where?
for example: I have a table with 4 filed(Id,UserId,Type,Sing).
I want select recorde that userid is 1 and if Type="None" , Sing should True.
(from d in db.Receive
where ((((d.SendType == "None") ? ((d.Signed) ? true : false) : true)) && userid==1)
select d).ToList();
when i use
((d.SendType == "None") ? ((d.Signed) ? true : false) : true)
it is select records that if Type="None" , Sing should True. but when add userid condition , don't return any records.
Isn't it better:
from d in db.Receive
where ((d.SendType == "None" && d.Signed) || d.SendType != "None") && userid == 1)
select d
and so?
(((d.SendType == "None") && (userid == 1)) ? ((d.Signed) ? true : false) : true)
Theres lots of brackets there...if I understand you correctly userid == 1 is used regardless so why not just have
where (((d.SendType == "None" && userid == 1) ? ((d.Signed) ? true : false) : true)))
select d).ToList();

Linq join with exists

I'm busy rewriting a system and are using Linq queries to extract data from the database. I am used to plain old TSQL and stored procedures so my Linq skills are not the best.
I have a sql query that I try to rewrite in Linq that contains a join, where clause and IN statements. I do get it right but when I run the sql query I get a different value as from the Linq query. Somewhere I'm missing something and can't find the reason.
Here is the SQL:
select
isnull(Sum(QtyCC) + Sum(QtyEmployee), 0) *
isnull(Sum(UnitPrice), 0)[TotalRValue]
from
tbl_app_KGCWIssueLines a
inner join tbl_app_KGCWIssue b on b.IssueNrLnk = a.IssueNrLnk
where
b.CreationDate >= '2011-02-01' and
a.IssueNrLnk IN (
select
IssueNrLnk
from
tbl_app_KGCWIssue
where
CustomerCode = 'PRO002' and
ISNULL(Tier1,'') = 'PRO002' and
ISNULL(Tier2,'') = 'HAMD01' and
ISNULL(Tier3,'') = '02' and
ISNULL(Tier4,'') = '02001' and
ISNULL(Tier5,'') = 'PTAHQ001' and
ISNULL(Tier6,'') = '035' and
ISNULL(Tier7,'') = '' and
ISNULL(Tier8,'') = '' and
ISNULL(Tier9,'') = '' and
ISNULL(Tier10,'') = ''
)
And here is the Linq:
ctx.ObjectContext.tbl_app_KGCWIssue
.Join(ctx.ObjectContext.tbl_app_KGCWIssueLines,
i => i.IssueNrLnk, l => l.IssueNrLnk, (i, l) => new { i, l })
.Where(o => o.i.CreationDate >= IntervalStartDate)
.Where(p => ctx.ObjectContext.tbl_app_KGCWIssue
.Where(a =>
a.CustomerCode == CustomerCode &&
a.Tier1 == employee.Tier1 &&
a.Tier2 == employee.Tier2 &&
a.Tier3 == employee.Tier3 &&
a.Tier4 == employee.Tier4 &&
a.Tier5 == employee.Tier5 &&
a.Tier6 == employee.Tier6 &&
a.Tier7 == employee.Tier7 &&
a.Tier8 == employee.Tier8 &&
a.Tier9 == employee.Tier9 &&
a.Tier10 == employee.Tier10)
.Select(i => i.IssueNrLnk)
.Contains(p.l.IssueNrLnk))
.Sum(p => p.l.UnitPrice * (p.l.QtyEmployee + p.l.QtyCC));

Resources