I use MVC 4 and There are 5 dropdownlist in my view. when dropdownlist selected text and clicked button search I want to select from 4 table where dropdownlist selected . and if dropdownlist don't selected not checked in condition.
(from met in db.tblMet
from useMet in db.tblUseMet.Where(m => m.UseMetID == met.UseMetID_FK).DefaultIfEmpty()
from typeMet in db.tblTypeMet.Where(m => m.TypeMetID == met.TypeMetID_FK).DefaultIfEmpty()
from mod in db.tblMod.Where(m => m.ModID == met.ModID_FK).DefaultIfEmpty()
from affair in db.tblAffairs.Where(m => m.AffairID == met.AffairID_FK).DefaultIfEmpty()
from desert in db.tblDeserts.Where(m => m.DesertID == met.DesertID_FK).DefaultIfEmpty()
from city in db.tblCities.Where(m => m.CityID == met.CityID_FK).DefaultIfEmpty()
from user in db.tblUsers.Where(m => m.UserID == met.UserIDCreate_FK).DefaultIfEmpty()
from userCh in db.tblUsers.Where(m => m.UserID == met.UserIDChange_FK).DefaultIfEmpty()
from setting in db.tblSettings.Where(m => m.SettingID == met.SettingID_FK).DefaultIfEmpty()
from sim in db.tblSims.Where(m => m.SimID == mod.SimID_FK).DefaultIfEmpty()
from typemod in db.tblTypeMod.Where(m => m.TypeModID == sim.TypeModID_FK_Kind).DefaultIfEmpty()
from gro in db.tblGroupMet.Where(m => m.GroupMetID == met.GroupMetID_FK).DefaultIfEmpty()
from group1 in db.tblMetRelateGroups.Where(x => x.MetID_FK == met.MetID).DefaultIfEmpty()
from status in db.tblStatus1.Where(m => m.StatusID == met.StatusID_FK).DefaultIfEmpty()
where ((city.CityID == City1||city.CityID !=null)
&& (typeMet.TypeMetID == Type1 || typeMet.TypeMetID != null)
&& (useMet.UseMetID == Usemeter1|| useMet.UseMetID != null)
&& (group1.GroupMetID_FK ==Group1 || group1.GroupMetID_FK != null)
&& (affair.AffairID ==Affair1 || affair.AffairID != null)
//|| desert.DesertID==Desert1
)
I want to selected dropdownlist selected and if don't select any, not checked in query. in above code select zero record.
You simply use the fluent syntax for this purpose. Here is an example:
var lQuery = from met in db.tblMet;
if (City1 != null)
lQuery = lQuery.Where(r => r.CityID == City1);
...
This way you can dynamically add conditions to your query.
If you want to add conditions with an logical OR you need a predicate builder, see https://stackoverflow.com/a/1775057/3936440.
Related
I have a query that select all Photos if its public, and only if friends if visibility is private in this code.
_communityDbContext
.Photos
.Where(x => (
x.Privacy == 1 ||
(x.Privacy == 2 &&
_communityDbContext.Friendships.FirstOrDefault(d => x.CreatedBy.Id == user1 && d.FriendUser.Id == user2) !=
null)
)
);
But I trying to extract this piece of code to reuse in another queries
_communityDbContext.Friendships.FirstOrDefault(d => x.CreatedBy.Id == user1 && d.FriendUser.Id == user2) != null
Is possible to call an function and make the code like that:
_communityDbContext
.Photos
.Where(x => (
x.Privacy == 1 ||
(x.Privacy == 2 &&
hasFriendship(x.CreatedBy.Id, user))
)
);
I fond a solution, the method invocation must be done to an expression, not to a function call. So I can extract that part of code by doing
public Expression<Func<Photo, bool>> Visible()
{
return x => (
x.Privacy == 1 ||
(x.Privacy == 2 &&
_communityDbContext.Friendships.FirstOrDefault(d => x.CreatedBy.Id == 3 && d.FriendUser.Id == 3) !=
null)
);
}
And calling this by
.where(Visible())
I have created two views that return exactly the same columns from the same tables. The only difference between the two views is they filter on different parameters. I have added these into my .dbml file
(Picture of views in dbml) This has then auto generated two classes for these two views.
In my code depending on the value of the property Filter one of the two views is queried, either current or previous. I need these views to be returned as the same type. So that IOrderedQueryable<> items has one return type.
Currently they are returning as either clientOrdersQueryCurrent or clientOrdersQueryPrevious. If I set IOrderedQueryable<> items to either one of these and attempt to cast the other type then this causes a runtime error.
IOrderedQueryable<> items;
bool filterQuery = false;
if (!string.IsNullOrEmpty(OrderNumber) || DateFrom != null || Dateto != null || !string.IsNullOrEmpty(TrackingNumber) || UserId != null)
{
filterQuery = true;
}
if (Filter == "Current")
{
if (filterQuery)
{
items = dataContext.clientOrdersQueryCurrents.Where(o => o.client_id == currentClientIdProvider.GetCurrentClientId()
&& (string.IsNullOrEmpty(OrderNumber) || o.OrderNumber.Contains(OrderNumber))
&& (DateFrom == null || o.OrderPlaced >= DateFrom)
&& (Dateto == null || o.OrderPlaced <= Dateto)
&& (string.IsNullOrEmpty(TrackingNumber) || o.TrackingReference.Contains(TrackingNumber))
&& (UserId == null || o.UserId == UserId)).OrderByDescending(o => o.OrderPlaced);
}
else
{
items = dataContext.clientOrdersQueryCurrents.Where(o => o.client_id == currentClientIdProvider.GetCurrentClientId()).OrderByDescending(o => o.OrderPlaced);
}
}
else if (Filter == "Previous")
{
if (filterQuery)
{
items = dataContext.clientOrdersQueryPrevious.Where(o => o.client_id == currentClientIdProvider.GetCurrentClientId()
&& (string.IsNullOrEmpty(OrderNumber) || o.OrderNumber.Contains(OrderNumber))
&& (DateFrom == null || o.OrderPlaced >= DateFrom)
&& (Dateto == null || o.OrderPlaced <= Dateto)
&& (string.IsNullOrEmpty(TrackingNumber) || o.TrackingReference.Contains(TrackingNumber))
&& (UserId == null || o.UserId == UserId)).OrderByDescending(o => o.OrderPlaced);
}
else
{
items = dataContext.clientOrdersQueryPrevious.Where(o => o.client_id == currentClientIdProvider.GetCurrentClientId()).OrderByDescending(o => o.OrderPlaced);
}
}
else
{
//Default call - current orders
items = dataContext.clientOrdersQueryCurrents.Where(o => o.client_id == currentClientIdProvider.GetCurrentClientId()).OrderByDescending(o => o.OrderPlaced);
}
The only thing I can currently think of to resolve this is to create a class and have the query map the result to the class after it returns.
What is the best way to do this?
The ORM I am currently using is NHibernate.
Better to map to some common class
IOrderedQueryable<CommonItem> items;
items = dataContext.clientOrdersQueryCurrents.Select(e => new CommonItem{...});
...
items = dataContext.clientOrdersQueryPrevious.Select(e => new CommonItem{...});
It can be AutoMapper's ProjectTo method
items = dataContext.clientOrdersQueryPrevious.ProjectTo<CommonItem>();
I have two queries, the first returns all "Open" records where the reply-by-date has not passed and the second returns all "Open Unviewed" records where the reply-by-date has not passed and the record has not been viewed by the user (no entry in table RfqVieweds). In this scenario the user has not viewed any of the 1000 records so all 1000 are returned. The second to last line in each query (right before "select new RfqDto()") is where the difference is between the two queries.
The first query takes about 45 seconds to return 1000 records. The second query takes about 4 seconds to return the same 1000 records. Why? How do I get the first query to run as fast as the second?
Query 1:
var groupQuery = Rfqs.Where(rfqs => rfqs.IsPrimaryEmail && (rfqs.Contract != "Upstream"))
.GroupBy(rfqs => new {rfqs.RFQ_RFISeqNum})
.Select(g => new {g.Key.RFQ_RFISeqNum, RfqId = g.Max(p => p.RfqId)});
var query = (from m in groupQuery
join t in Rfqs on new {m.RfqId} equals new {t.RfqId}
join s in RfqSupplementals on new {RfqSeqNumber = t.RFQ_RFISeqNum} equals new {s.RfqSeqNumber}
from rfqViewed in RfqVieweds.Where(rv => rv.RfqId == t.RfqId && rv.SalesRep == salesrep).DefaultIfEmpty()
from rfqStarred in RfqUserStarreds.Where(rs => rs.RfqSeqNumber == t.RFQ_RFISeqNum && rs.SalesRep == salesrep).DefaultIfEmpty()
let rcn = RfqCommentNotifications.Where(r => r.RfqSequenceNum == t.RFQ_RFISeqNum && r.SalesRep == salesrep).Select(d => d.LastViewed).FirstOrDefault()
let ch = RfqsChangeHistories.Where(r => r.RfqRfiSeqNum == t.RFQ_RFISeqNum && chgHistList.Contains(r.Action)).OrderByDescending(r => r.Id).FirstOrDefault()
where (isRfqUser == false || ((t.assignedTo == salesrep || t.secndAssignedTo == salesrep || t.addlAssignedTo == salesrep)
|| (agencies.Contains(t.Agency) && (t.assignedTo == null || t.assignedTo.Trim() == string.Empty)
&& (t.secndAssignedTo == null || t.secndAssignedTo.Trim() == string.Empty) && (t.addlAssignedTo == null || t.addlAssignedTo.Trim() == string.Empty))))
&& (!isRfqUser || t.HouseOpportunity == false)
&& t.IsDeleted == false && t.IsPrimaryEmail
&& (t.ReplyByDate > now || (t.ReplyByDate == null && t.IsManualRfq))
select new RfqDto()
Query 2:
var groupQuery = Rfqs.Where(rfqs => rfqs.IsPrimaryEmail && (rfqs.Contract != "Upstream"))
.GroupBy(rfqs => new {rfqs.RFQ_RFISeqNum})
.Select(g => new {g.Key.RFQ_RFISeqNum, RfqId = g.Max(p => p.RfqId)});
var query = (from m in groupQuery
join t in Rfqs on new {m.RfqId} equals new {t.RfqId}
join s in RfqSupplementals on new {RfqSeqNumber = t.RFQ_RFISeqNum} equals new {s.RfqSeqNumber}
from rfqViewed in RfqVieweds.Where(rv => rv.RfqId == t.RfqId && rv.SalesRep == salesrep).DefaultIfEmpty()
from rfqStarred in RfqUserStarreds.Where(rs => rs.RfqSeqNumber == t.RFQ_RFISeqNum && rs.SalesRep == salesrep).DefaultIfEmpty()
let rcn = RfqCommentNotifications.Where(r => r.RfqSequenceNum == t.RFQ_RFISeqNum && r.SalesRep == salesrep).Select(d => d.LastViewed).FirstOrDefault()
let ch = RfqsChangeHistories.Where(r => r.RfqRfiSeqNum == t.RFQ_RFISeqNum && chgHistList.Contains(r.Action)).OrderByDescending(r => r.Id).FirstOrDefault()
where (isRfqUser == false || ((t.assignedTo == salesrep || t.secndAssignedTo == salesrep || t.addlAssignedTo == salesrep)
|| (agencies.Contains(t.Agency) && (t.assignedTo == null || t.assignedTo.Trim() == string.Empty)
&& (t.secndAssignedTo == null || t.secndAssignedTo.Trim() == string.Empty) && (t.addlAssignedTo == null || t.addlAssignedTo.Trim() == string.Empty))))
&& (!isRfqUser || t.HouseOpportunity == false)
&& t.IsDeleted == false && t.IsPrimaryEmail
&& (rfqViewed == null && (t.ReplyByDate > now || (t.ReplyByDate == null && t.IsManualRfq)))
select new RfqDto()
You probably need to look at the query plan to see the true reason for the timing difference, as it depends on the actual data.
The two queries are different and if they happen to return the same number of rows, then Sql will have no way of knowing that in advance.
I can give you an example of one circumstance which could cause the difference.
First of all, lets simplify the query to
var query = (from m in groupQuery
join t in Rfqs on new { m.RfqId } equals new { t.RfqId }
from rfqViewed in RfqVieweds.Where(rv => rv.RfqId == t.RfqId && rv.SalesRep == salesrep).DefaultIfEmpty()
where
t.ReplyByDate > now
select new RfqDto()
Now suppose you have 1 million rows in Rfqs and only 1000 records have a ReplyByDate values in the future. If ReplyByDate is not indexed, then that means that sql has to read and check all million rows before returning the selected 1000 rows.
But if the query becomes
var query = (from m in groupQuery
join t in Rfqs on new { m.RfqId } equals new { t.RfqId }
from rfqViewed in RfqVieweds.Where(rv => rv.RfqId == t.RfqId && rv.SalesRep == salesrep).DefaultIfEmpty()
where
(t.ReplyByDate > now
&& rfqViewed == null
select new RfqDto()
and if it happens that there are only 10000 rows in Rfqs that do not have a record in RfqVieweds, and if rfqViewed has a suitable index that Sql can determine this quickly, then that means that Sql will only need to look at these 10000 records, which may be faster.
Note, If there are any rows with ReplyDates in the future that have been reviewed, then the two queries will not return the same records.
My requirement is to make boolean value (IsPC=true) only if I found any value with IsCurrent = true from the list and second condition is to filter the list with G or W codes and third condition is to check the PCBNumber length ==15 with only one from the list.
How short can i able to reduce the below query using LINQ method syntax
below is my query
var CurrentQ= p.List.Where(x => x.IsConCurrent== true);
if (CurrentQ.Count() > 0)
{
var NCurrentQwithWorQ = p.List.Where(x => x.Codes == Codes.W|| x.Codes== Codes.Q).Count();
if (NCurrentQwithWorQ != null)
{
var PCBNumber = p.List.Where(x => x.PCBNumber .Length == 15).Count();
if (PCBNumber == 1)
{
isPC = true;
}
}
}
You can use all conditions in same query like below,
var PCBNumber= p.List.Where(x => x.IsConCurrent== true && (x.Codes == Codes.W|| x.Codes== Codes.Q) && x.PCBNumber.Length == 15);
if (PCBNumber !=null && PCBNumber.Count() == 1)
{
isPC = true;
}
I'm not trying to debug what you wrote, but isn't this really what you're looking for--that is, daisy-chaining your Where conditions?
var isPC = p.List.Where(x => x.IsConCurrent == true).Where(x => x.Codes == Codes.W || x.Codes == Codes.Q).Where(x => x.PCBNumber.Length == 15).Count() == 1;
Both solutions suggested above are correct.
p.List.Where(x => x.IsConCurrent== true && (x.Codes == Codes.W|| x.Codes== Codes.Q) && x.PCBNumber.Length == 15);
p.List.Where(x => x.IsConCurrent == true).Where(x => x.Codes == Codes.W || x.Codes == Codes.Q).Where(x => x.PCBNumber.Length == 15).Count()
Actually they are performed in the same way. The Where function does not force immediate iteration through the data source. Only when you execute the Count function, LINQ will process row by row and execute criterion by criterion to find out which values should be calculated.
I can only suggest you add the Take(2) operator after the where clause. In this case LINQ will stop after finding the first two rows that matches provided criterion and other rows will not be processed.
p.List.Where(x => x.IsConCurrent == true)
.Where(x => x.Codes == Codes.W || x.Codes == Codes.Q)
.Where(x => x.PCBNumber.Length == 15)
.Take(2).Count()
This question already has answers here:
Dynamic where clause (OR) in Linq to Entities
(2 answers)
Closed 5 years ago.
I am working in ASP.NET MVC, I have a scenario where user can select multiple options to get list of doctors, this is how my action looks like.
public JsonResult DoctorsList(int? specialization , int? city, int? area, int? insurance_company, string doctor_name )
Any of these arguments can have some value and any number of them can be null also all of can be null in that I will return all the records.
Now I know a long and complicated way where I can make different combinations of these arguments and check which one is null and which one is not and then write my query based on that.
But is there any other shorter more efficient way?
Right now I am using OR conditions to get records like this
var doctors = db.Doctors.Where(e =>
e.specialization == specialization ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin=>sin.company_id).ToList().Contains(insurance_company) ||
e.first_name == doctor_name ||
e.last_name == doctor_name
)
.Select(s => new
{
doctor_name = s.first_name + " " + s.last_name
}).ToList();
But I want it to work in combinations, For Example Selecting Doctors with specialization_id = 1 and city_id=2 , of other combinations like this. But OR condition will be true if only one condition matches
For your scenario i think this approach might work rather than going around if else conditions. And i think && should be used to filter out exactly but you could use || operator if thats what you want,
var doctors = db.Doctors.Where(e =>
(specialization != null && e.specialization == specialization) &&
(city != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city) &&
(area != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area) &&
(insurance_company != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin => sin.company_id).ToList().Contains(insurance_company)) &&
(doctor_name != "" && e.first_name == doctor_name || e.last_name == doctor_name)
)
.Select(s => new
{
doctor_name = s.first_name + " " + s.last_name
}).ToList();
This is what I was looking for #imanshu15 answer gave me a hint.
var doctors = db.Doctors.Where(e =>
(specialization != null && e.specialization == specialization) || (specialization == null)
).Where(e =>
(city != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city) || (city == null)
).Where(e =>
(area != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area) || (area == null)
).Where(e =>
(insurance_company != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin => sin.company_id).ToList().Contains(insurance_company)) || (insurance_company == null)
).Where(e =>
(doctor_name != null && e.first_name == doctor_name) || (doctor_name == null)
)