Entity Framework querying error - c#

Why does this work:
List<Item> items = ndb.Items.Where(m => m.ProductId == id).OrderByDescending(m => m.Id).ToList();
int itemid = items[0].Id;
bool wlexists = ndb.Wishlists.Any(m => m.ItemId == itemid && m.UserEmail == User.Identity.Name);
And this doesn't :
List<Item> items = ndb.Items.Where(m => m.ProductId == id).OrderByDescending(m => m.Id).ToList();
bool wlexists = ndb.Wishlists.Any(m => m.ItemId == items[0].Id && m.UserEmail == User.Identity.Name);

It must work if the items had value i.e not null . What error you are getting???
Do like this.
List<Item> items = ndb.Items.Where(m => m.ProductId == id).OrderByDescending(m => m.Id).ToList();
if(items!=null)
bool wlexists = ndb.Wishlists.Any(m => m.ItemId == items[0].Id && m.UserEmail == User.Identity.Name);

Related

Using AND in JOIN in LINQ

I have such a SQL:
SELECT Items.ItemCode AS code, Items.ItemName AS name, ISNULL(PLID.PriceOverule,Items.ItemPrice) AS price from tblPLItemsDetail PLID
INNER JOIN tblItems Items ON PLID.ItemID = Items.ItemID
AND Items.ValidityTo IS NULL
WHERE PLItemID = #PLItemID
AND PLID.ValidityTo IS NULL
AND (PLID.ValidityFrom >= #LastUpdated OR #LastUpdated IS NULL)
I put this on LINQ:
details = context.TblPlitemsDetail
.Join(imisContext.TblItems,
p => p.ItemId,
i => i.ItemId,
(p, i) => new { TblPlitemsDetail = p, TblItems = i })
.Where(r => r.TblPlitemsDetail.PlitemId == PLItemID
&& r.TblPlitemsDetail.ValidityTo == null
&& (r.TblPlitemsDetail.ValidityFrom >= Convert.ToDateTime(model.last_update_date) || model.last_update_date == null))
.Select(x => new CodeNamePrice()
{
code = x.TblItems.ItemCode,
name = x.TblItems.ItemName,
price = (x.TblPlitemsDetail.PriceOverule == null) ? x.TblItems.ItemPrice.ToString() : x.TblPlitemsDetail.PriceOverule.ToString()
}).ToList();
I've rewritten most of the code but I have not implemented the AND Items.ValidityTo IS NULL predicate in the JOIN.
How to do it correctly?
As it is an INNER JOIN you can specify the extra predicate (Items.ValidityTo IS NULL) in a LINQ Where clause:
details = context.TblPlitemsDetail
.Join(imisContext.TblItems, p => p.ItemId, i => i.ItemId, (p, i) => new { TblPlitemsDetail = p, TblItems = i })
.Where(r => !r.TblItems.ValidityTo.HasValue)
.Where(r => r.TblPlitemsDetail.PlitemId == PLItemID && r.TblPlitemsDetail.ValidityTo == null && (r.TblPlitemsDetail.ValidityFrom >= Convert.ToDateTime(model.last_update_date) || model.last_update_date == null))
.Select(x => new CodeNamePrice() { code = x.TblItems.ItemCode, name = x.TblItems.ItemName, price = (x.TblPlitemsDetail.PriceOverule == null) ? x.TblItems.ItemPrice.ToString() : x.TblPlitemsDetail.PriceOverule.ToString() }).ToList();

Use same, looked-up value across multiple linq Where clauses without looking up more than once

I have a LINQ query which has three Where clauses. In each Where clause I am looking up the same set of items in order to compare values:
var items = _umbracoHelper.GetPage(ItemsPage.ModelTypeAlias).Children
.Where(x => level1Category == 0 || x
.GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)
.Select(y => y.Id).Contains(level1Category))
.Where(x => !level2Categories.Any() || x
.GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)
.Select(y => y.Id).Intersect(level2Categories.AsEnumerable()).Any())
.Where(x => !level3Categories.Any() || x
.GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)
.Select(y => y.Id).Intersect(level3Categories.AsEnumerable()).Any());
Is there a way I can get the value of UmbracoAlias.Items.Categories once and store that value to be used in the other where clauses without causing the GetPropertyValue method to execute more than once?
You can pair up each item with category IDs, like this:
var items = _umbracoHelper.GetPage(ItemsPage.ModelTypeAlias).Children
.Select(c => new {
Child = c
, CategoryIds = c
.GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)
.Select(y => y.Id)
.ToList()
})
.Where(x => level1Category == 0 || x.CategoryIds.Contains(level1Category))
.Where(x => !level2Categories.Any() || x.CategoryIds.Intersect(level2Categories.AsEnumerable()).Any())
.Where(x => !level3Categories.Any() || x.CategoryIds.Intersect(level3Categories.AsEnumerable()).Any())
.Select(x => x.Child);
This does the filtering on children paired up with their category IDs, and then keeps only the Child object in the final projection.
You could further simplify this by combining all three Where clauses:
var items = _umbracoHelper.GetPage(ItemsPage.ModelTypeAlias).Children
.Where(c => {
var categoryIds = c
.GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)
.Select(y => y.Id)
.ToList();
if (level1Category != 0 && !categoryIds.Contains(level1Category)) {
return false;
}
if (level2Categories.Any() && !categoryIds.Intersect(level2Categories.AsEnumerable()).Any()) {
return false;
}
if (level3Categories.Any() && !categoryIds.Intersect(level3Categories.AsEnumerable()).Any()) {
return false;
}
return true;
});

C# search by many parameters Entity Framework 6.0

In my table I have 4 columns: BAZAR_TEXT, CATEGORY, COUNTY, PRICE and I would like to search records by parameters from textboxes: search, category, county, priceFrom, priceUntil
var searchResult = db.bazar.Include(c => c.images).Where(da => da.BAZAR_TEXT.Contains(search) || search == null);
var categoryResult = searchResult.Where(x => x.CATEGORY == category || category == null);
var countyResult = categoryResult.Where(x => x.DISTRICT == county || county == null);
var priceFromResult = countyResult.Where(x => x.PRICE >= priceFrom);
var priceUntilResult = priceFromResult.Where(x => x.PRICE <= priceUntil);
return View(priceUntilResult.ToList().ToPagedList(page ?? 1, 10));
and need to return list to view.
If I search only by searchResults all is OK
var searchResult = db.bazar.Include(c => c.images).Where(da => da.BAZAR_TEXT.Contains(search) || search == null);
return View(searchResult.ToList().ToPagedList(page ?? 1, 10));
but If I add other results list is null.
Note: all parameters from textboxes can be null, but columns in table are not null.
var searchResult = db.bazar.Include(c => c.images).AsQueryable();
if(search != null){
searchResult = searchResult.Where(da => da.BAZAR_TEXT.Contains(search));
}
if(category != null){
searchResult = searchResult.Where(x => x.CATEGORY == category);
}
if(county != null){
searchResult = searchResult.Where(x => x.DISTRICT == county);
}
if(priceFrom != null){
searchResult = searchResult.Where(x => x.PRICE == priceFrom);
}
if(priceUntil != null){
searchResult = searchResult.Where(x => x.PRICE <= priceUntil);
}
return View(searchResult.ToList().ToPagedList(page ?? 1, 10));
There is difference between null and string empty. So if you search with empty textbox:
WebEntities db = new WebEntities();
var searchResult = db.bazar.Include(c => c.images);
if (!string.IsNullOrEmpty(search))
{
searchResult = searchResult.Where(da => da.BAZAR_TEXT.Contains(search));
}
if (!string.IsNullOrEmpty(category))
{
searchResult = searchResult.Where(x => x.CATEGORY == category);
}
if (!string.IsNullOrEmpty(county))
{
searchResult = searchResult.Where(x => x.DISTRICT == county);
}
if (priceFrom != null)
{
searchResult = searchResult.Where(x => x.PRICE >= priceFrom);
}
if (priceUntil != null)
{
searchResult = searchResult.Where(x => x.PRICE <= priceUntil);
}
return View(searchResult.ToList().ToPagedList(page ?? 1, 10));
You should reverse the order of condition evaluation
.Where(x => x.CATEGORY == category || category == null)
to
.Where(x => category == null || x.CATEGORY == category )

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();

OrderByDescending doesn't work in nested linq statement

In Linqpad, i can see the correct list. But in code, after putting in the list collection, order by doesn't work for BeginDate. If i use BeginDate with Max, it works. I don't understand where i am wrong?
var templist = contentRepository
.Get(q => (q.Status == (int)StatusEnum.Active) &&
(q.CategoryId == category.GetHashCode() || q.Category.ParentId == category.GetHashCode())
&& q.MinorVersion == 0
&& q.MajorVersion > 0)
.GroupBy(q => q.VersionId)
.OrderByDescending(q => q.Key)
.Select(q => new
{
VersionId = q.Key,
Id = q.Max(x => x.Id),
MajorVersion = q.Max(x => x.MajorVersion),
UpdatedAt = q.Max(x => x.UpdatedAt),
//BeginDate = q.Max(x=>x.BeginDate),
BeginDate = (q.OrderByDescending(x => x.Id).Take(1).Select(x=>x.BeginDate)).First(),
Title = (q.OrderByDescending(x => x.Id).Take(1).Select(x => x.Title)).First(),
ShowOnHomePage = (q.OrderByDescending(x => x.Id).Take(1).Select(x=>x.ShowOnHomePage)).First()
})
.OrderByDescending(x => x.BeginDate)
.Take(maxItemCount)
.ToList();
List<ContentEntity> contents = new List<ContentEntity>();
templist.ForEach(q => contents.Add(
contentRepository
.Get(x => x.VersionId == q.VersionId && x.MajorVersion == q.MajorVersion && x.MinorVersion == 0)
.FirstOrDefault()
));
return contents.Where(q => q.ShowOnHomePage == true)
.OrderByDescending(q => q.MajorVersion)
.OrderByDescending(q => q.BeginDate)
.Take(maxItemCount)
.ToList();
You are ordering by Id, not by BeginDate. Equivalent code for
q.Max(x => x.BeginDate)
Will be
q.OrderByDescending(x => x.BeginDate).Take(1).Select(x => x.BeginDate).First()
Or simplified
q.OrderByDescending(x => x.BeginDate).First().BeginDate

Categories

Resources