Operator should be ‘AND’ and not a ‘OR’.
I am trying to refactor the following code and i understood the following way of writing linq query may not be the correct way. Can somone advice me how to combine the following into one query.
AllCompany.Where(itm => itm != null).Distinct().ToList();
if (AllCompany.Count > 0)
{
//COMPANY NAME
if (isfldCompanyName)
{
AllCompany = AllCompany.Where(company => company["Company Name"].StartsWith(fldCompanyName)).ToList();
}
//SECTOR
if (isfldSector)
{
AllCompany = AllCompany.Where(company => fldSector.Intersect(company["Sectors"].Split('|')).Any()).ToList();
}
//LOCATION
if (isfldLocation)
{
AllCompany = AllCompany.Where(company => fldLocation.Intersect(company["Location"].Split('|')).Any()).ToList();
}
//CREATED DATE
if (isfldcreatedDate)
{
AllCompany = AllCompany.Where(company => company.Statistics.Created >= createdDate).ToList();
}
//LAST UPDATED DATE
if (isfldUpdatedDate)
{
AllCompany = AllCompany.Where(company => company.Statistics.Updated >= updatedDate).ToList();
}
//Allow Placements
if (isfldEmployerLevel)
{
fldEmployerLevel = (fldEmployerLevel == "Yes") ? "1" : "";
AllCompany = AllCompany.Where(company => company["Allow Placements"].ToString() == fldEmployerLevel).ToList();
}
Firstly, unless AllCompany is of some magic custom type, the first line gives you nothing.
Also I have a doubt that Distinctworks the way You want it to. I don't know the type of AllCompany but I would guess it gives you only reference distinction.
Either way here'w what I think You want:
fldEmployerLevel = (fldEmployerLevel == "Yes") ? "1" : "";
var result = AllCompany.Where(itm => itm != null)
.Where(company => !isfldCompanyName || company["Company Name"].StartsWith(fldCompanyName))
.Where(company => !isfldSector|| fldSector.Intersect(company["Sectors"].Split('|')).Any())
.Where(company => !isfldLocation|| fldLocation.Intersect(company["Location"].Split('|')).Any())
.Where(company => !isfldcreatedDate|| company.Statistics.Created >= createdDate)
.Where(company => !isfldUpdatedDate|| company.Statistics.Updated >= updatedDate)
.Where(company => !isfldEmployerLevel|| company["Allow Placements"].ToString() == fldEmployerLevel)
.Distinct()
.ToList();
Edit:
I moved Distinct to the end of the query to optimize the processing.
How about trying like this;
AllCompany = AllCompany .Where(company => (company => company.Statistics.Created >= createdDate)) && (company.Statistics.Updated >= updatedDate));
If every part of query is optional (like created date, last update date..) then you can build linq query string.
Here's a sneaky trick. If you define the following extension method in its own static class:
public virtual IEnumerable<T> WhereAll(params Expression<Predicate<T> filters)
{
return filters.Aggregate(dbSet, (acc, element) => acc.Where(element));
}
then you can write
var result = AllCompany.WhereAll(itm => itm != null,
company => !isfldCompanyName || company["Company Name"].StartsWith(fldCompanyName),
company => !isfldSectorn || fldSector.Intersect(company["Sectors"].Split('|')).Any(),
company => !isfldLocation || fldLocation.Intersect(company["Location"].Split('|')).Any(),
company => !isfldcreatedDate || company.Statistics.Created >= createdDate,
company => !isfldUpdatedDate || company.Statistics.Updated >= updatedDate,
company => !isfldEmployerLevel || company["Allow Placements"].ToString() == fldEmployerLevel)
.Distinct()
.ToList();
Related
public int being = 0;
public void Insert(Currency current, int number)
{
being = db.Currency.Where(x => x.ForDate == current.ForDate)
.Where(x => x.TitleId == current.TitleId)
.Where(x => x.Value == current.Value).Count(x=>x.Id > 0);
if (being == 0)
{
db.Currency.AddOrUpdate(current);
}
}
it's my code works so slowly, because of getting date but it is not necessary, i don't know other way.
maybe something like :
db.Currency.Find().Value.Equals(current.Value).where...where...
I think your main problem is the .Count(x => x.Id > 0), which forces the evaluation of all the conditions before and actually get the total number.
If you can, replace it with Any. In that way, it just has to get one row at most:
bool isBeing = db.Currency
.Where(x => x.ForDate == current.ForDate
&& x.TitleId == current.TitleId
&& x.Value == current.Value
&& x.Id > 0
)
.Any();
You can do all your conditions in just one where, and also you can skip having a bool variable to check your conditions
if(db.Currency.Where(x => x.ForDate == current.ForDate
&& x.TitleId == current.TitleId && x.Value == current.Value && x.Id > 0).Any())
{
db.Currency.AddOrUpdate(current);
}
I would like to rewrite GetCurrentAuction into single LINQ request:
private AuctionInfo GetCurrentAuction()
{
var auctions = Auctions.List().ToList();
var liveAuction = auctions
.Where(AuctionIsLive)
.OrderBy(a => a.StartDate)
.FirstOrDefault();
if (liveAuction != null)
{
return liveAuction;
}
var openAuction = auctions
.Where(AuctionIsOpen)
.OrderBy(a => a.StartDate)
.FirstOrDefault();
if (openAuction != null)
{
return openAuction;
}
// next upcoming auction
return auctions
.Where(a => a.StartDate >= DateTime.UtcNow)
.OrderBy(a => a.StartDate)
.FirstOrDefault();
}
private bool AuctionIsLive(AuctionInfo auction)
{
// WorkflowStage is int
return auction.WorkflowStage == LIVE_WORKFLOW_STAGE;
}
private bool AuctionIsOpen(AuctionInfo auction)
{
return auction.WorkflowStage == OPEN_WORKFLOW_STAGE;
}
Could someone suggest how to achieve this? It looks like using auctions.GroupBy(a => a.WorkflowStage) doesn't bring me closer to the solution.
You can indicate preference by ordering them - something like:
return
Auctions.List().ToList() //--> ToList() not needed here?
.Where
( a =>
AuctionIsLive(a) ||
AuctionIsOpen(a) ||
a.StartDate >= DateTime.UtcNow
)
.OrderBy
( a =>
AuctionIsLive( a ) ? 0 :
AuctionIsOpen( a ) ? 1 : 2
)
.ThenBy( a => a.StartDate )
.FirstOrDefaut();
You can use very usefull ?? ( https://msdn.microsoft.com/en-us/library/ms173224.aspx ) operator and achive this:
var result = auctions.Where(AuctionIsLive).OrderBy( x => x.StartDate).FirstOrDefault() ??
auctions.Where(AuctionIsOpen).OrderBy( x => x.StartDate).FirstOrDefault() ??
auctions.Where(a => a.StartDate >= DateTime.UtcNow).OrderBy(a => a.StartDate).FirstOrDefault();
return result;
It depends on the datasource and LINQ provider you're using.
For example, if you use LINQ to SQL the preferent way of doing it would be using Expressions to save your memory and end up with the answer simular to #fankyCatz's:
return Auctions.Where(a => a.WorkflowStage == LIVE_WORKFLOW_STAGE).OrderBy(x => x.StartDate).FirstOrDefault() ??
Auctions.Where(a => a.WorkflowStage == OPEN_WORKFLOW_STAGE).OrderBy(x => x.StartDate).FirstOrDefault() ??
Auctions.Where(a => a.StartDate >= DateTime.UtcNow).OrderBy(a => a.StartDate).FirstOrDefault();
However, using only LINQ to Objects I would end up with the answer simular to #Clay's one, just would improve readability with mapping:
public static Dictionary<int, Func<AuctionInfo, bool>> Presedence =
new Dictionary<int, Func<AuctionInfo, bool>>
{
{ 0, a => a.WorkflowStage == LIVE_WORKFLOW_STAGE },
{ 1, a => a.WorkflowStage == OPEN_WORKFLOW_STAGE },
{ 2, a => a.StartDate >= DateTime.UtcNow },
};
//in your GetCurrentAuction()
return Auctions.Where(a => Presedence.Any(p => p.Value(a)))
.OrderBy(a => Presedence.First(p => p.Value(a)).Key)
.ThenBy(a => a.StartDate)
.FirstOrDefault();
I order two types of query. I want to show the result as one. if the first query and second query have count these both are merge and show the results of one. So i have created 3 list like jobs, jobs1, jobs2. I am getting values into jobs1 and jobs2. Then i have assigned using union into jobs3
Code
IQueryable<Job> jobs = _repository.GetJobs();
IQueryable<Job> jobs1 = _repository.GetJobs();
IQueryable<Job> jobs2 = _repository.GetJobs();
List<int> lstId = null;
List<int> lstUpdatedListId = null;
List<int> lstConId=null;
var order = _db.GetOrderDetails().Where(od => od.Masters.Id != null && od.OrderId == od.Master.OrderId && od.Master.Status == true && od.ValidityTill.Value >= currentdate).OrderByDescending(od => od.ValidityTill).Select(ord => ord.Master.Id.Value);
var order1 = _vasRepository.GetOrderDetails().Where(od => od.Masters.ConId != null && od.OrderId == od.Masters.OrderId && od.Masters.PaymentStatus == true && od.ValidityTill.Value >= currentdate).OrderByDescending(od => od.ValidityTill).Select(ord => ord.Masters.ConId.Value);
var updatedVacancyList = _repository.GetJobs().Where(c => c.UpdatedDate != null && updateFresh <= c.UpdatedDate).Select(c => c.Id);
if (order1 .Count() > 0)
{
lstConId = order1.ToList();
Func<IQueryable<Job>, IOrderedQueryable<Job>> orderingFunc = query =>
{
if (order1.Count() > 0)
return query.OrderByDescending(rslt => lstConId.Contains(rslt.Con.Id)).ThenByDescending(rslt=>rslt.CreatedDate);
else
return query.OrderByDescending(rslt => rslt.CreatedDate);
};
jobs1 = orderingFunc(jobs);
}
if (order.Count() > 0)
{
lstId = order.ToList();
lstUpdatedJobsListId = updatedVacancyList.ToList();
Func<IQueryable<Job>, IOrderedQueryable<Job>> orderingFunc = query =>
{
if (order.Count() > 0)
return query.OrderByDescending(rslt => lstId.Contains(rslt.Id)).ThenByDescending(rslt => lstUpdatedJobsListId.Contains(rslt.Id)).ThenByDescending(rslt=>rslt.CreatedDate);
if (updatedVacancyList.Count() > 0)
return query.OrderByDescending(rslt => lstUpdatedJobsListId.Contains(rslt.Id)).ThenByDescending(rslt => rslt.UpdatedDate);
else
return query.OrderByDescending(rslt => rslt.CreatedDate);
};
jobs2 = orderingFunc(jobs);
}
jobs = jobs1.Union(jobs2);
and i am getting an error while run the application as follows,
The text data type cannot be selected as DISTINCT because it is not comparable.
I need help to rectify this issue. I want to order in descending also.
One of your columns in Database is "Text" type. Convert it to varchar(MAX)
I have following a table called Resources where it has couple of capacity fields ; CapM3, CapUD and CapMT.
I would like to get list of resources where capacity is equal or larger than a default supplied resource.
public static IList<Resources> GetSwapResources(string resourceID)
{
//selected resource
var res = db.Resources.FirstOrDefault(p => p.ResourceID == resourceID);
//select all active resources excluding selected
var resources = db.Resources.Where(p => p.Active == true && p.ResourceID != resourceID);
//not sure how to filter here
return resources.ToList();
}
}
I think I will be able to do this by looping for desired results. But, can that be handled within LINQ query itself?
I think I will be able to do this by looping for desired results. But,
can that be handled within LINQ query itself?
Yes, you can chain as many conditions to the Where clause as you wish:
var res = db.Resources
.Where(p => p.ResourceID == resourceID)
.Where(p => p.Active == true)
.Where(p => p.CapM3 >= 1234)
.Where(p => p.CapM3 >= 5678);
Or if you wanted to use OR instead of AND:
var res = db.Resources
.Where(p => p.ResourceID == resourceID)
.Where(p => p.Active == true)
.Where(p => p.CapM3 >= 1234 || p.CapM3 >= 5678);
I figured out on how to achieve desired result :
public static IList<Resources> GetSwapResources(string resourceID)
{
//selected resource
var res = db.Resources.FirstOrDefault(p => p.ResourceID == resourceID);
//select all active resources excluding selected
var resources = db.Resources.Where(p => p.Active == true && p.ResourceID != resourceID);
.Where(a => a.CapM3 <= res.CapM3 && a.CapMT <= res.CapMT && a.CapUD<= res.CapUD);
return resources.ToList();
}
}
Please see the code below:
var pcPageList = db.PcPages
.Where(m =>
m.Quarter == exactQuarter &&
m.Url == pageUrl &&
m.UpdatedOn.ToDateTime().Date.ToString("dd/MMM").ToLower() == "02/nov")
.OrderBy(m => m.UpdatedOn)
.FirstOrDefault();
When I run this above, the application throws error says: "ToDateTime" is not implemented yet. Anyone please can advice ?
How about:
var updateStart = DateTime.ParseExact("02/nov", "dd/MMM", CultureInfo.InvariantCulture);
var updateEnd = updateStart.AddDays(1.0);
var pcPageList = db.PcPages
.Where(m =>
m.Quarter == exactQuarter &&
m.Url == pageUrl &&
m.UpdatedOn >= updateStart &&
m.UpdatedOn < updateEnd)
.OrderBy(m => m.UpdatedOn)
.FirstOrDefault();
I think, you should be calling ToDateTime using Convert class as:
Convert.ToDateTime(m.UpdatedOn).Date...
And remove the Date in between as:
Convert.ToDateTime(m.UpdatedOn).ToString("dd/MMM").ToLower() == "02/nov"
Rather than doing a string comparison, it would be more efficient to compare the date components directly. I haven't tested this, but something like the following may work:
var pcPageList = db.PcPages
.Where(m => m.Quarter == exactQuarter && m.Url == pageUrl)
// You may need to materialize the results of the query at this point
// or use Convert.ToDateTime(...) instead of ToDateTime()
.Select(m => new { Row = m, UpdatedOn = m.UpdatedOn.ToDateTime() })
.Where(a => a.UpdatedOn.Month == 11 && a.UpdatedOn.Day == 2)
.Select(a => a.Row)
.OrderBy(m => m.UpdatedOn)
.FirstOrDefault();