How to dynamically add or remove where clause in LINQ - c#

Here is my LINQ query that needs to update to dynamic where clause.
If parameter's id value is 0 then where clause should return all records else where clause should match records as per id value.
public async Task<IEnumerable<dynamic>> GetFilteredRowsByID(int id)
{
return from m in _context.TableName
where m.id == (id != 0 ? id : /*AllRecordsHere*/ )
join ...
join ...
select new {...}
}
I use Asp.Net Core 2.2. Is it possible without writing another method witout where clause for this?

I will use AsQueryable lazy query instead of one LINQ Query to do it. because it's more readable i think.
var query = (from m in _context.TableName.AsQueryable() select m );
if(id != 0)
query = query.Where(w=>w.id == id);
query = ( from m in query
join ...
join ...
select new {..}
)

Try condition:
where id == 0 || m.id == id
in case when id == 0, whole expression evaluates to true, otherwise it is false and second condition m.id == id would be checked.

I'm not sure that you can achieve this cleanly with 100% expression syntax, but you can with fluent syntax:
var result = _context.TableName;
if (id != 0) result = result.Where(m => m.Id == id);
result = result.Join(...).Join(...).Select(m => m.new {...});
A key benefit of fluent syntax is that it simplifies query composition.
You can freely mix expression and fluent syntax.

Move id != 0 ? outside of the equals expression:
public async Task<IEnumerable<dynamic>> GetFilteredRowsByID(int id)
{
return from m in _context.TableName
where id != 0 ? m.id == id : true
join ...
join ...
select new {...}
}
Hopefully EF would be able to optimize the where true to remove the condition entirely.

Related

How to search on the basis of all the variable parameters

I am trying to write a search functionality wherein the user can search on the basis of Id, UserName and status. The data corresponding to these search filters are in different tables, so I have to put joins on these tables.
Of course user can search on the basis of Id and UserName or UserName and status and all the combinations that can be considered from these 3 filters.
What I have done is made different functions to address these combinations.
Is there a way that this can be achieved with one method using linq. I am trying to avoid the if-else and switch.
I have already looked into
Add Conditional Join Dynamically with Linq
and
LINQ - Joins in a dynamic query
This is my code where I am searching on the basis of all the parameters
public List<Application> GetApplication(int? applicationId, string userName, string status)
{
_applicationlist.Clear();
if (applicationId != 0 && !string.IsNullOrWhiteSpace(userName) && !string.IsNullOrWhiteSpace(status))
{
var application = (from a in _targetDbContext.DbSet<ApplicationEntity>()
join u in _targetDbContext.DbSet<UserEntity>() on a.InDraftPersonnel equals GetUserID(userName)
join v in _targetDbContext.DbSet<ApplicationVersionEntity>() on a.Id equals v.ApplicationId
join s in _targetDbContext.DbSet<ApplicationStatusEntity>() on v.VersionStatus equals s.Id
where a.Id.Equals(applicationId)
where u.UserName.Equals(userName)
where s.StatusName.Equals(status)
select (new Application
{
Id = a.Id,
AppName = a.AppName,
CreatedBy = a.CreatedBy,
CreatedOn = a.CreatedOn
})).FirstOrDefault();
_applicationlist.Add(application);
}
return _applicationlist;
}
The thing is I am not sure if the user would be searching with all the parameters of with just one.
Any help would be appreciated.
Remove if and try this:
where (!applicationid.HasValue || applicationid == 0 || a.Id.Equals(applicationId)) &&
(string.IsNullOrWhiteSpace(userName) || u.UserName.Equals(userName)) &&
(string.IsNullOrWhiteSpace(status) || s.StatusName.Equals(status))
With this where clause all parameters are optional and if one of those is null or empty those parameter don't affect query result and All combination is supported.
With
...
where a.Id.Equals(applicationId) && u.UserName.Equals(userName) && s.StatusName.Equals(status)
...
... all parameters must match
...
where a.Id.Equals(applicationId) || u.UserName.Equals(userName) || s.StatusName.Equals(status)
...
... at least one parameter must match.
...
where a.Id.Equals(applicationId) && u.UserName.Equals(userName) && s.StatusName.Equals(status)
...
is equivalent to
...
where a.Id.Equals(applicationId)
where u.UserName.Equals(userName)
where s.StatusName.Equals(status)
...
See also: Boolean logical operators (C# reference)
Note that you can construct LINQ queries pice-wise.
var query = source.Join(..) ...;
if (applicationId.HasValue) {
query = query.Where(x => x.Id == applicationId.Value);
}
if (!String.IsNullOrEmpty(userName)) {
query = query.Where(x => x.UserName == userName);
}
if (!String.IsNullOrEmpty(status)) {
query = query.Where(x => x.StatusName == status);
}
query = query.Select(x => ...);

Using lambda expressions on joined basic LINQ query

When making a basic LINQ query you can later use lambda expressions to add a where clause like this: query.Where(c => (init.Contains(c.user)));.
My problem is that I need to add two where clauses on a query that uses a join in the basic LINQ query.
I'm trying to replace my old basic LINQ queries with added lambda expressions so that i prevent duplicated code.
This is my code;
var query = from c in db.Clgcom
join u in db.Dvusr
on c.Comaut equals u.Gitusr
// && (initialen.Contains(c.Tstusr) // <-- query.Where(c => (initialen.Contains(c.Tstusr)));
// This is what im trying to replace// ^^ This works because its in the same table
// || initialen.Contains(u.Clgusr)) // <-- What do i type when i want to include both these conditions?
&& (c.Modid.StartsWith("C")
|| c.Modid.StartsWith("M"))
select c;
if(filter != null){
query = query.Where(c => (initialen.Contains(c.Tstusr)
|| initialen.Contains(u.Clgusr)));
// This doesn't work
}
Is there a way to use a lambda expression that would achieve adding these two conditions in my where clause?
Or should i replace ALL basic LINQ queries with using lambda expressions?
Basically you need to also defer the select by selecting both c and u to begin with and later just selecting c.
var temp = from c in db.Clgcom
join u in db.Dvusr on c.Comaut equals u.Gitusr
where c.Modid.StartsWith("C") || c.Modid.StartsWith("M")
select new {c, u};
if(filter != null){
temp = temp.Where(x => initialen.Contains(x.c.Tstusr)
|| initialen.Contains(x.u.Clgusr));
var query = temp.Select(x => x.c);
If the relationship between Clgcom and Dvusr is many to one then you could do the following as Clgcom should have a Dvusr navigation property based on the foreign key relationship.
var query = from c in db.Clgcom
where (c.Modid.StartsWith("C") || c.Modid.StartsWith("M")) && c.Dvuser != null
select c;
if(filter != null){
query = query.Where(c => initialen.Contains(c.Tstusr)
|| initialen.Contains(c.Dvusr.Clgusr));

Include("myTable") in Linq to Entities in Silverlight

I need help, I have a method to Access to my Orders table:
public IQueryable<Orders> GetOrders()
{
return this.ObjectContext.Orders.Include("UnitDetail");
}
it Works very well, and I can see it from the window Data Source, and can see Orders and UnitDetail from here
But I need make some considerations for the selected rows, so I made the next method:
public IQueryable<Orders> GetOpenOrders(string _iduni)
{
ObjectSet<Orders> orders = this.ObjectContext.Orders;
ObjectSet<Estatus> estatus = this.ObjectContext.Estatus;
ObjectSet<DetailUnit> units = this.ObjectContext.DetailsUnit;
ObjectSet<ServiceType> servicetype = this.ObjectContext.ServiceType;
var query =
(from o in orders
join e in estatus on o.ID equals e.IDOrder
join u in units on o.IDUni equals u.IDUni
join t in servicetype on u.IDType equals t.IDType
where o.IDUni.Equals(_iduni)
&& !estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA")
&& oe.IDOrder == o.ID)
select o).Distinct();
return query.AsQueryable();
}
This show me the correct recs, but what happend? why I don't see UnitDetail, when I inspect the result UnitDetail is null, how I can do for put the Include clausule in this new method??
Thanks a lot in advance
Because you haven't put the Include in your new method anywhere.
EDITED: to remove the unused joins.
You should be able to just use Include as you did in your GetOrders method, and so have it as a part of your existing orders variable. You are not actually using those joins anywhere, are you intending to?
Like this:
public IQueryable<Orders> GetOpenOrders(string _iduni)
{
var query =
(from o in this.ObjectContext.Orders.Include("UnitDetail")
where o.IDUni.Equals(_iduni)
&& !this.ObjectContext.Estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA")
&& oe.IDOrder == o.ID)
select o).Distinct();
return query.AsQueryable();
}

Writing the LINQ equaivalent of a SQL join

This is the SQL query I have written:
select * from Addresses a
join ProviderAddresses pa on a.address_k = pa.address_k
where pa.provider_k = 'ABC123'
and pa.active = 1
and a.active = 1
and pa.addresstype_rtk = 'HOME'
And this is the LINQ query I wrote for it:
public IQueryable<Addresses> GetAddressesesForProvider(string provider_k, string addresstype_rtk)
{
var query = from a in this.Context.Addresses
join pa in this.Context.ProviderAddresses on a.Address_K equals pa.Address_K
where pa.AddressType_RTK == addresstype_rtk
&& pa.Active == true
&& a.Active == true
select a;
return query;
}
But it is wrong. The LINQ one return thousands of records and the SQL one returns only one record.
It is IQueryable because later I need to go through its results with a for-each loop.
In the SQL I am passing hard coded values for testing but in my code for me LINQ method I also pass the same hard coded values so that is not the issue.
Looks like you may have just missed adding the provider_k condition to the where;
public IQueryable<Addresses> GetAddressesesForProvider(string provider_k, string addresstype_rtk)
{
var query = from a in this.Context.Addresses
join pa in this.Context.ProviderAddresses on a.Address_K equals pa.Address_K
where pa.Provider_K == provider_k &&
pa.AddressType_RTK == addresstype_rtk &&
pa.Active == true &&
a.Active == true
select a;
return query;
}

How to get SQL query into LINQ form in C# code

How can I convert the following SQL queries into LINQ query form in C#, .NET 3.5 code:
1)
select COUNT(distinct Skill_Name)
from Table1
where Department = 'ABC' and Skill_Name is not null
2)
select distinct location, country from Customer where Customer_Code ='1001';
I suspect you want:
var query = from entry in dbContext.Table1
where entry.Department == "ABC" && entry.SkillName != null
select entry.SkillName;
var count = query.Distinct().Count();
Or using extension method syntax, in one go:
var count = dbContext.Table1
.Where(entry => entry.Department == "ABC" &&
entry.SkillName != null)
.Select(entry => entry.SkillName)
.Distinct()
.Count();
As shown by mesiesta, you can combine query expressions with calls not supported within query expressions, but I tend to assign the query expression to an intermediate variable... I personally find it clearer, but use whichever you (and your team) prefer.
Something like this
int count = (from p in Table1
where p.Department == "ABC" && p.Skill_Name != null
select p.Skill_Name).Distinct().Count();
For second query you can use this
var query= (from p in Customer
where p.Customer_Code=="1001"
select new { Location=p.location ,Country=p.country}).Distinct();
you can use linqpad to convert to linq and lambda expressions

Categories

Resources