Linq Lambda Expressin Where Conditions And Performance Problem - c#

I created where conditions with linq lambda expression for reporting. My conditions are running very slowly or it is throwing error.
Error Detail: Evoluation timed out.
How can i find correct query?
My codes:
var query = Worker.Members
.Where(u => string.IsNullOrEmpty(model.TcNumber) || u.TcNumber.Contains(model.TcNumber))
.Where(u => string.IsNullOrEmpty(model.FullName) || u.FullName.Contains(model.FullName))
.Where(u => model.BirthYear == null || u.BirthDate.Year >= model.BirthYear)
.Where(u => model.BirthYearLevel == null || u.BirthDate.Year <= model.BirthYearLevel)
.Where(u => model.BirthYearLevel == null || u.BirthDate.Year <= model.BirthYearLevel)
.Where(u => model.GenderId == null || u.GenderId == model.GenderId)
.Where(u => model.DistrictCode == null || u.Contacts.Any(c => c.DistrictCode == model.DistrictCode && c.IsActive))
.Where(u => model.StreetCode == null || u.Contacts.Any(c => c.StreetCode == model.StreetCode && c.IsActive))
.Where(u => model.ExteriorDoor == null || u.Contacts.Any(c => c.ExteriorDoor == model.ExteriorDoor && c.IsActive))
.Where(u => model.InteriorDoor == null || u.Contacts.Any(c => c.InteriorDoor == model.InteriorDoor && c.IsActive))
.Where(u => model.DisabledGroupId == null || u.Disableds.Any(d => d.ReportDisabledGroups.Any(c => c.DisabledGroupId == model.DisabledGroupId)))
.Where(u => model.ContributionTypeId == null || u.Demands.Any(d => d.ContributionTypeId == model.ContributionTypeId && !d.IsDeleted))
.Where(u => model.DemandStatusId == null || u.Demands.Any(d => d.DemandStatusId == model.DemandStatusId && !d.IsDeleted))
.Where(u => model.DemandDateStart == null || u.Demands.Any(d => d.DemandDate >= model.DemandDateStart && !d.IsDeleted))
.Where(u => model.DemandDateEnd == null || u.Demands.Any(d => d.DemandDate <= model.DemandDateEnd && !d.IsDeleted))
.Where(u => u.IsTcCitizen == model.IsForeign)
.Where(u => u.IsDisabled == model.IsDisabled)
.Where(u => u.IsAlive == model.IsAlive);

The correct pattern (assuming Worker.Members is an IQueryable, not an IEnumerable) here is to conditionally add the criteria, like this:
var query = Worker.Members;
if (!string.IsNullOrEmpty(model.TcNumber))
query = query.Where(u => u.TcNumber.Contains(model.TcNumber));
if (!string.IsNullOrEmpty(model.FullName)
query = query.Where(u => u.FullName.Contains(model.FullName));
if (!model.BirthYear == null)
query = query.Where(u => u.BirthDate.Year >= model.BirthYear);
. . .

Did you check this?
Here detailed descriptions are given.

Related

How can I use conditional Order with EntityFramework/linq

Ever time when I have many options to order and filter, in my repository I have using "switch" to decide, but the code is very duplicate.
How can I use the coditional order to remove the duplicate code?
Whould you have a solution to optimize this code?
Sample Code:
IEnumerable<Products> products;
switch (orderBy)
{
case "Create":
products = _GFazContext.Products
//... many conditions like:
.Where(r => (productId == null || r.ProductId == productId))//Duplicate code
.Where(r => (groupId == null || r.GroupId == groupId))//Duplicate code
.Where(r => (statusId == null || r.StatusId == statusId)) //Duplicate code
//Condition about the order
.Where(r => (data1 == null || r.CreateDate >= data1))
.Where(r => (data2 == null || r.CreateDate <= data2))
.Include(r => r.Group) //Duplicate code
//Specific order
.OrderBy(p => p.CreateDate)
.Skip(pagination.SkipRecords)//Duplicate code
.Take(pagination.PageSize);//Duplicate code
break;
case "Update":
products = _GFazContext.Products
//... many conditions like:
.Where(r => (productId == null || r.ProductId == productId))//Duplicate code
.Where(r => (groupId == null || r.GroupId == groupId))//Duplicate code
.Where(r => (statusId == null || r.StatusId == statusId)) //Duplicate code
//conditions about the order
.Where(r => (data1 == null || r.LastUpdate >= data1))
.Where(r => (data2 == null || r.LastUpdate <= data2))
.Include(r => r.Group) //Duplicate code
//Specific orders
.OrderBy(p => p.LastUpdate)
.Skip(pagination.SkipRecords)//Duplicate code
.Take(pagination.PageSize);//Duplicate code
break; break;
default:
products = _GFazContext.Products
//... many conditions like:
.Where(r => (productId == null || r.ProductId == productId))//Duplicate code
.Where(r => (groupId == null || r.GroupId == groupId))//Duplicate code
.Where(r => (statusId == null || r.StatusId == statusId)) //Duplicate code
//Condition about the order
.Where(r => (data1 == null || r.ReleaseDate >= data1))
.Where(r => (data2 == null || r.ReleaseDate <= data2))
.Include(r => r.Group) //Duplicate code
//Specific orders
.OrderBy(p => p.ReleaseDate)
.Skip(pagination.SkipRecords)//Duplicate code
.Take(pagination.PageSize);//Duplicate code
break;
}
return products;
Something like this
IQueryable<Products> products = _GFazContext.Products
.Where(r => (productId == null || r.ProductId == productId))
.Where(r => (groupId == null || r.GroupId == groupId))
.Where(r => (statusId == null || r.StatusId == statusId));
switch (orderBy)
{
case "Create":
products = products
.Where(r => (data1 == null || r.CreateDate >= data1))
.Where(r => (data2 == null || r.CreateDate <= data2))
.Include(r => r.Group)
.OrderBy(p => p.CreateDate);
break;
case "Update":
products = products
.Where(r => (data1 == null || r.LastUpdate >= data1))
.Where(r => (data2 == null || r.LastUpdate <= data2))
.Include(r => r.Group)
.OrderBy(p => p.LastUpdate);
break;
default:
products = products
.Where(r => (data1 == null || r.ReleaseDate >= data1))
.Where(r => (data2 == null || r.ReleaseDate <= data2))
.Include(r => r.Group)
.OrderBy(p => p.ReleaseDate);
break;
}
products = products
.Skip(pagination.SkipRecords)
.Take(pagination.PageSize);
return products;
Try This -
IEnumerable<Products> products;
products = _GFazContext.Products
.Where(r => (productId == null || r.ProductId == productId))
.Where(r => (groupId == null || r.GroupId == groupId))
.Where(r => (statusId == null || r.StatusId == statusId))
.Where(r => orderBy == "Create" ? (data1 == null || r.CreateDate >= data1) : (orderBy == "Update" ? (data1 == null || r.LastUpdate >= data1) : (data1 == null || r.ReleaseDate >= data1)))
.Where(r => orderBy == "Create" ? (data2 == null || r.CreateDate <= data2) : (orderBy == "Update" ? (data2 == null || r.LastUpdate <= data2) : (data2 == null || r.ReleaseDate <= data2)))
.Include(r => r.Group)
//Specific order
.OrderBy(p => orderBy == "Create" ? p.CreateDate : (orderBy == "Update"? p.LastUpdate : p.ReleaseDate))
.Skip(pagination.SkipRecords)
.Take(pagination.PageSize);

Short record of if / null

I have the following code:
decimal? sumFreightAmount = (db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount));
if (sumFreightAmount.HasValue)
{
// my actions
}
else
{
sumFreightAmount = 0;
}
I can write it the following way:
decimal sumFreightAmount = (
db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount) != null)
?
(db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount)) : 0;
but in this place I call linq extension twice (and have a long record). I have read, that I can write more shorter it in the latest version of C#, like
decimal sumFreightAmount = (db.Trips.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year).Sum(p => p.FreightAmount)?.0;
but can't find it. What is the shortest record?
The best way is using GetValueOrDefault
decimal sumFreightAmount = db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount)
.GetValueOrDefault();
EDIT: As #IvanStoev pointed out, you can also use the null coalescing operator in this case, which is a tad bit shorter:
decimal sumFreightAmount = db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount) ?? 0;

C# use left outer join in LINQ

This is my method:
public IEnumerable<Web_Vendor> GetSaleBrands()
{
using (var _db = new LuxedecorContext())
{
IQueryable<Web_Vendor> web_vendors = _db.Web_Vendor.
Where(x =>
(_db.Web_Promotion.Where(z => z.VendorID != string.Empty
&& z.Static == true && z.Percent != 0 &&
(x.WebPromotion.Expires >= DateTime.Now || x.WebPromotion.Expires == null))
.Select(r => r.VendorID).Contains(x.VendorID))
||
(_db.NavItems.Where(y => x.WebPromotion.VendorID == y.SC1
&& !(y.Promotion == "" || y.Promotion == null)
&& (y.PromotionStart <= DateTime.Now) && (y.PromotionEnd >= DateTime.Now || y.PromotionEnd == null))
.Select(g => g.SC1).Contains(x.WebPromotion.VendorID)))
.Where(x => x.Active == true).OrderBy(x => x.NameExtra)
.ThenBy(x => x.Sequence);
var a = web_vendors.ToList(); // 16 values
var b = web_vendors.Include(x => x.WebPromotion).ToList(); // 13 values
}
throw new NotImplementedException();
}
I need to Include nullable values to my collection of Web_Vendors. I know, it's famous question, but I need to return collection of Web_Vendors instead of collection of dynamic types. Is it possible?

Get result from multiple where conditional statements in LINQ

I am trying to get the result based upon the values of variables temp_DestinationGroupName, temp_CountryName and temp_RateTypeId.
If any of these variables are null or 0, it should not be included in where clause and rest statements should work and bring the result. I am getting zero rows using this query. Kindly suggest me something with these conditions in where clause. i tried following solutions on stackoverflow but still not getting the desired result.
var Rows = _CustomerRatesList.Where(w => (w.Id != rates.Id)
&& (w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName!= null)
&& (w.CountryName == temp_CountryName || temp_CountryName!=null)
&& (w.RateTypeId == temp_RateTypeId || temp_RateTypeId !=0));
(w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName!= null)
Your condition here will return true as long as your input variable temp_DestinationGroupName is not null. I don't think that's what you had in mind.
You can split in many Where to make your request more readable :
var Rows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName != temp_DestinationGroupName || temp_DestinationGroupName != null)
.Where(w => w.CountryName != temp_CountryName || temp_CountryName != null)
.Where(w => w.RateTypeId != temp_RateTypeId || temp_RateTypeId !=0);
Notice that you must use != in first conditioon of all Where, so you'll get all data except when it's null. In your logic, may be the conditions will be == :
var Rows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName == null)
.Where(w => w.CountryName == temp_CountryName || temp_CountryName == null)
.Where(w => w.RateTypeId == temp_RateTypeId || temp_RateTypeId ==0);
Each Where result is an IEnumerable, Rows will be a IEnumerable. If you want a List, just add .ToList()
I got the solution to this problem, now i am getting filtered result.
Thank you all for your time :)
var otherRows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName == null)
.Where(w => w.CountryName == temp_CountryName || temp_CountryName == null)
.Where(w => w.RateTypeId == temp_RateTypeId || temp_RateTypeId == 0);

Is there a way I can select only certain fields from a .Include( in a LINQ Query?

Given the following:
var questions = _questionsRepository
.GetAll()
.Where(q => q.Problem.SubTopicId == subTopicId || subTopicId == 0)
.Where(q => q.QuestionStatusId == questionStatusId || questionStatusId == 0)
.Where(q => q.AssignedTo == assignedTo || assignedTo == "0")
.Where(q => q.ModifiedBy == modifiedBy || modifiedBy == "0")
.Include(q => q.Problem)
.Include(q => q.Answers)
.ToList();
Is there a way I can return the question and answer data plus only the fields SubTopicId and ProblemId from the Problem table/class ?
Try adding select at the end of query
var problems = _questionsRepository
.GetAll()
.Where(q => q.Problem.SubTopicId == subTopicId || subTopicId == 0)
.Where(q => q.QuestionStatusId == questionStatusId || questionStatusId == 0)
.Where(q => q.AssignedTo == assignedTo || assignedTo == "0")
.Where(q => q.ModifiedBy == modifiedBy || modifiedBy == "0")
.Include(q => q.Problem)
.Include(q => q.Answers)
.Select(x=>new
{
SubTopicId = x.Problem.SubTopicId,
ProblemId = x.Problem.ProblemId
}).ToList();

Categories

Resources