How to use OR operator in Linq - c#

I want to use OR function in my linq query.
Ex:
Sql:
select * from tblusers where userid=1 and status='a' or status='b';
Linq:
var result= _Repository.selectAll().where(x=>x.UserID==1 && x.status=="a" OR x.status=="B");
It's does work for linq query. so does anyone have any idea?

So you are aware about the && operator for comparison, then why not make a try with || operator? Anyway here is the solution for your problem, Following code will get you the result with UserID is 1 and status is either a or B.
_Repository.selectAll().where(x=>x.UserID==1 && (x.status=="a" || x.status=="B"));

Create an array of status you want to check and then use contains. something like this.
var statusList = new[] {"a", "b"};
.Where(x=> x.UserID == 1 && statusList.Contains(x.status));

Adding my 2 cents in here, there is another way you can write your sql query in C# which more or less resembles the sql syntax.
var result = from x in _Repository.SelectAll() where x.UserID == 1 && (x.Status == "a" || x.Status == "B") select x;
This syntax is Query Syntax/Expression where as your snippet is Method Syntax/Expression. Both will achieve same results. Also behind the scene, query syntax is compiled to Method syntax.
At compile time, query expressions are converted to Standard Query Operator method calls according to the rules set forth in the C# specification. Any query that can be expressed by using query syntax can also be expressed by using method syntax. However, in most cases query syntax is more readable and concise.

Or other approach with List.Contains, which generates sql query like
SELECT * FROM tblusers WHERE userid=1 AND status IN ('a','b');
var acceptedStatus = new List<string> { 'a', 'b' };
var result= _Repository.selectAll()
.Where(x => x.UserID == 1)
.Where(x => acceptedStatus.Contains(x.Status));
Notice that instead of && operator you can use another Where function and chain them. Can be more readable then fit all conditions in one line.

Try code:
var result =( from x in _Repository.selectAll()
where x.UserID==1 && (x.status=="a" || x.status=="B") select x);
another Solution
var result =( from x in _Repository.selectAll().where(c=>c.status=="a" || x.status=="B")
where x.UserID==1 select x);

Related

Multiple queries and poor perfomance in Entity Framework when using Distinct and Order By

The following LINQ query in EF (EFCore, v2.2.1)
var x = context.Exchange
.Include(q => q.Input)
.Where(q => q.InputId != 1&&
q.Input.CreatedOnUtc > DateTime.Parse("2019-11-25") &&
q.Input.UserId == 2 &&
q.BotConversationId == 3)
.Distinct()
.OrderBy(q => q.Input.CreatedOnUtc)
.FirstOrDefault()
Ends up giving the profiled SQL results (simplified)
select * from (
select distinct e.*
from Exchange e, ExchangeInput i
where e.InputId = i.InputId
and e.InputId <> 1
and i.UserId = 2
and e.BotConversationId = 3
)
select * from ExchangeInput
Why does it need to do two separate queries? The second query being horrendous when ExchangeInput might have millions of rows.
Surely, this would suffice:
select * from (
select distinct e.*, i.CreatedOnUtc
from Exchange e, ExchangeInput i
where e.InputId = i.InputId
and e.InputId <> 1
and i.UserId = 2
and e.BotConversationId = 3
) a
order by a.CreatedOnUtc
Also - putting the Distinct after the order by gives only 1 query as I would expect.
Fixing the problem is easy enough. Adding a .Select(...) before the .Distinct or removing the .Distinct() will do it. But the initial, poorly performing code, doesn't seem immediately problematic when reviewing it.
I would start by suggesting that calling Distinct() before a FirstOrDefault() is unnecessary. The first row in a "non-distinct" query should always be the same as a "distinct" query when you have an OrderBy! As you mentioned in your last sentence, it seems that removing the Distinct() should only create one query.
Separate to your question, I would also suggest calculating DateTime.Parse("2019-11-25") outside of the query. That should allow you to pass it to the database server as a parameter and that might make your query even more efficient.
All in all, I would try:
var dateFilter = DateTime.Parse("2019-11-25");
var x = context.Exchange
.Include(q => q.Input)
.Where(q => q.InputId != 1 &&
q.Input.CreatedOnUtc > dateFilter &&
q.Input.UserId == 2 &&
q.BotConversationId == 3)
.OrderBy(q => q.Input.CreatedOnUtc)
.FirstOrDefault()

Optional condition not working linq

I having some problem in Optional condition in Lambda express like
var shouldCheckDate = !string.IsNullOrEmpty(fromDate);
var result = (from r in db.Notify
where r.ApplicationId == applicationId
&& (shouldCheckDate || r.CreatedDate.Date > date)
select r
).Count;
problem is here it always excuting both condition either shouldCheckDate true are false. I am doing any thing wrong?
This is due to the fact, that LINQ is translated to SQL and SQL, in contrast to C#, executes all parts of a condition, no matter if one of them allready returned true.
You could compose the IQueryable by adding the where clauses only when needed:
var query = db.Notify;
query = query.Where(r => r.ApplicationId == applicationId);
if (shouldCheckDate) {
query = query.Where(r => r.CreatedDate.Date > date);
}
var result = query.Count();
You have OR statement here,
(shouldCheckDate || r.CreatedDate.Date > date)
so even one of these conditions which is true is enough for whole statement to be true.
Maybe r.CreatedDate.Date is always > date ?

Proper Syntax for Extension Method Query

I am trying to do something similar to my previous post, except I am using extension methods instead of LINQ. I get an error telling me that && cannot be used, so how would I search within a table using two strings entered by the user?
var query = (App.DBConnection.Table<Notes>().Where(
c => c.Note.Contains(textBox1.Text) && c => c.Note.Contains(textBox2.Text))).Single();
TextBox_Results.Text = query.Note;
Remove the second lambda operator c =>
var query = App.DBConnection.Table<Notes>()
.Where(c => c.Note.Contains(textBox1.Text)
&& c.Note.Contains(textBox2.Text)))
.Single();
Apart from that, i would use FirstOrDefault instead of Single. The latter throws an InvalidOperationException if there are no elements or if there are more than one. The former just returns null if no item matches the predicate in the Where.
You don't need to declare the c variable again
Where(c => c.Note.Contains(textBox1.Text) && c => c.Note.Contains(textBox2.Text)))
should be
Where(c => c.Note.Contains(textBox1.Text) && c.Note.Contains(textBox2.Text)))

Conditional OR has no effect in Linq-to-entities?

I stumbled across a null ref exception today in one of my Linq-To-Entitites queries and wondered how that could be possible. It seems an conditional OR used as an OR-gate has no effect in Linq-To-Entities. A simplified example of my query is this:
from a in db.Articles
where a.Author == "John Doe"
&& (tag == null || a.Tags.Any(t => t.TagName == tag.TagName))
select a;
Now when tag is NULL, the right side of the where query still gets executed and a NULL reference exception occurs on tag.TagName. Maybe this is because Linq-To-Entities always translates the complete statement into SQL?
Anyhow ... how to get around this issue?
Thanks very much :)
var query = db.Articles.Where(x => x.Author == "John Doe");
query = tag == null
? query
: query.Where(x => x.TagName == tag.TagName);
or:
var query = from a in db.Articles
where a.Author == "John Doe"
select a;
query = tag == null
? query
: from a in query
where a.Tags.Any(t => t.TagName == tag.TagName)
select a;
Personally, I find the first one cleaner
Think about sql. Linq converts your code as a whole into sql query passing 'outside' objects as parameters and evaluating them. That's why it fails on evaluation of your null object.
It's a good practice to construct a linq query bit by bit based on conditions to reduce number of unnecessary code in resulted query, so it's better to split your query:
var query = db.Articles.Where(x => x.Author == "John Doe");
if( tag != null)
query = query.Where(x => x.TagName == tag.TagName);
Because your query will be evaluated and executed on selection you are welcome to add more conditions without worrying about multiple requests.

Using multiple .Where() calls or && conditions for LinqToEntities queries

Are the following two queries equivalent? If they are not equivalent, which performs better? Is there a way I can see the sql output of the queries?
var query1 = items.Where(i => i.Enabled == true).Where(i => i.Name == "Bob");
var query2 = items.Where(i => i.Enabled == true && i.Name == "Bob");
As Andrew says, the two options are equivalent. One practically useful difference is that you can easily generate conditions in the Where clause programmatically. For example if you wanted to exclude certain names:
var query = items;
for(string name in excluded)
query = query.Where(i => i.Name != excluded);
This is something that cannot be done easily when writing query using && operator.
Both queries will translate to the same SQL - you can use a tool like LinqPad to verify this if you want (I just did). The LINQ provider that translate your expression trees into T-SQL is smart enough to understand that these queries are synonymous. Of course this means that both queries will perform equally as well.

Categories