where condition in include, how? - linq

The code below is not working. I am getting exception "The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties."
What im doing wrong
public static MyEntity GetData(this IQueryable<MyEntity> source, int id, int year)
{
return source.Where(x => x.ID == id)
.Include(x => x.Childrens1)
.Include(x => x.Childrens2.where(y => y.Year == year))
.FirstOrDefault();
}

Where is not supported into Include expression, you only can use select, even nested. move where out of include
public static MyEntity GetData(this IQueryable<MyEntity> source, int id, int year)
{
return source
.Include(x => x.Childrens1)
.Include(x => x.Childrens2)
.Where(x => x.ID == id && x.Childrens2.Any(y => y.Year == year))
.FirstOrDefault();
}
Now, you also can unify where or filter inside FirstOrDefault

Related

Anonymous types mismatch LINQ to SQL query?

List<branch_rating> ObjRat = new List<branch_rating>();
ObjRat=(_Context.branch_rating
.GroupBy(a => a.restaurant_branch_id)
.Select(a => new { rating = a.Sum(b => b.rating), Name = a.Key })
.OrderByDescending(a => a.rating)).ToList();
I tried by putting query in var variable and then adding in object.
Below picture shows the error.
I want to get data from branch_rating table having four columns, I also tried by using var and then adding list data one by one in object.
It will be better if you make a custom class like DOTopResturant which includes data members branch_rating,branch_id and then make a object of type DOTopResturant , add every item in variable q into that object.
List<branch_rating> ObjRat = new List<branch_rating>();
ObjRat = _Context.branch_rating.ToList();
var q = (_Context.branch_rating
.GroupBy(a => a.restaurant_branch_id)
.Select(a => new { branch_rating = a.Sum(b => b.rating), branch_id = a.Key })
.OrderByDescending(a => a.branch_rating)).ToList();
List<DOTopResturant> ObjTopRes = new List<DOTopResturant>();
foreach (var item in q)
{
ObjTopRes.Add(new DOTopResturant() { branch_id = Convert.ToInt32(item.branch_id), branch_rating = Convert.ToInt32(item.branch_rating) });
}
return ObjTopRes;
Just read and understand what the error describes :
your are trying to convert an anonymous type (with 2 properties Name and Rating) to another object type branch_rating.
You have 2 solutions :
work with the anonymous type (using var) :
var ObjRat=(_Context.branch_rating
.GroupBy(a => a.restaurant_branch_id)
.Select(a => new { Rating = a.Sum(b => b.rating), Name = a.Key })
.OrderByDescending(a => a.rating))
.ToList();
And then, in your code, just access to Rating and Name properties of your list members.
work with your type defined branch_rating, by using it in your Select, and use the appropriate constructor.
List<branch_rating> ObjRat = new List<branch_rating>();
ObjRat=(_Context.branch_rating
.GroupBy(a => a.restaurant_branch_id)
.Select(a => new branch_rating() { <Your branch_rating properties assignments here> })
.OrderByDescending(a => a.rating)).ToList();
If your branch_rating object does not have an empty constructor, call the correct constructor with good arguments in the Select.
Change select (third row in the picture) to:
.Select(a => new DOTopRestaurant {rating = a.Sum(b => b.rating), Name = a.Key})
Delete the declaration of ObjRat and use var:
var ObjRat=(_Context.branch_rating
.GroupBy(a => a.restaurant_branch_id)
.Select(a => new { rating = a.Sum(b => b.rating), Name = a.Key })
.OrderByDescending(a => a.rating))
.ToList();
Your list is a list of the anonymous type not of type branch_rating.
If you want to convert it to branch_rating use another Select to create a new branch_rating(...) passing the appropriate parameters to the constructor.
PS You should also look at .NET naming conventions.

Can I change this Query into a method?

I am using Entity Framework and have to query a "Project" property a lot, which has a lot of properties which have to be included in the query, making the query bloated:
var project = await this.ProjectRepository.GetRaw().Where(x => x.ID == id).Include(x => x.Leader).Include(x => x.Users).Include(x => x.Firm).FirstOrDefaultAsync();
Please not that GetRaw() returns a IQueryable
Is there a way to construct some helper method where the "include" portion is added, while I dynamically pass in the rest of the query?
something like that:
public async Task<List<Project>> GetProjects(query)
{
return this.ProjectRepository.GetRaw().Include(x => x.Leader).Include(x => x.Users).Include(x => x.Firm) + query;
}
usage something like that:
public ProjectController
{
public void Test()
{
var result = GetProjects.Where(x => x.ID == 0).FirstOrDefaultAsync();
}
}
I think it should look more like this:
public ObjectQuery<Project> GetProjects()
{
return this.ProjectRepository.GetRaw()
.Include(x => x.Leader)
.Include(x => x.Users)
.Include(x => x.Firm);
}
Usage would look like this then:
var result = GetProjects().Where(x => x.ID == 0).FirstOrDefaultAsync();
You can create the expression as parameter and return it as IQueryable<T> so it can be continued by another query.
public IQueryable<Project> GetProjects(Expression<Func<Project, bool> query)
{
return this.ProjectRepository.GetRaw()
.Include(x => x.Leader)
.Include(x => x.Users)
.Include(x => x.Firm)
.Where(query);
}
Usage.
var project = await GetProjects(x => x.ID == 0).FirstOrDefaultAsync();

The cast to value type 'Int32' failed because the materialized value is null. Pls help me how to fixed it

I have some codes like this:
public int GetCount()
{
// Get the count of each item in the cart and sum them up
var s = BikesDB.ShoppingCartItems.Where(cart => cart.ShoppingCartID == ShoppingCartID1).Select(cart => cart.Quantity).Sum(cart => cart);
// Return 0 if all entries are null
return s;
}
And here what I got when I was debugging:
The cast to value type 'Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
I'm very appreciate any questions from yours, thank you so much!
Before doing the Sum, add DefaultIfEmpty(0) to the chain:
var s = BikesDB.ShoppingCartItems
.Where(cart => cart.ShoppingCartID == ShoppingCartID1)
.Select(cart => cart.Quantity)
.DefaultIfEmpty(0)
.Sum(cart => cart);
It will handle the case when you have no elements.
I believe that you need to throw in a Where call to filter out the items where Quantity is null, i.e.
var s = BikesDB.ShoppingCartItems.Where(cart => cart.ShoppingCartID == ShoppingCartID1 && cart.Quantity.HasValue).Sum(cart => cart.Quantity.Value);
For people who are getting the error (probably because you are using a join):
"does not contain a definition for 'DefaultIfEmpty'"
var s = BikesDB.ShoppingCartItems
.Where(cart => cart.ShoppingCartID == ShoppingCartID1)
.Select(cart => cart.Quantity)
.Sum(cart => cart)
.GetValueOrDefault(0);
In my case I needed it because of this join:
return Orders
.Join(
OrderLogisticss,
o => o.ID,
ol => ol.OrderID,
(o, ol) => new { Order = o, OrderLogistics = ol })
.Where(x => x.OrderLogistics.DepartureDate == date)
.Sum(x => x.Order.NumberOfCarts)
.GetValueOrDefault(0);

A fetch request must be a simple member access expression; '[100002]' is a SubQueryExpression instead

I get the following error:
"A fetch request must be a simple member access expression; '[100002]' is a SubQueryExpression instead. Parameter name: relatedObjectSelector"
Below is my query:
var query =
session.Query<Customer().Where(cus => cus.CustomerId == customerId)
.Fetch(c => c.CustomerType) // Parent CustomerType
.Fetch(c => c.CustomerOrders) // Child Collection of orders
.ThenFetch(co => co.Select(it => it.Item)).ToList(); // A parent of CustomerOrder
If I take the 'ThenFetch' out then I do not get that error. However, I do need to retrieve the Item object.
Any ideas?
Thanks
Can't you just apply the select on the resulting CustomerOrder?
var query =
session.Query<Customer().Where(cus => cus.CustomerId == customerId)
.Fetch(c => c.CustomerType)
.Fetch(c => c.CustomerOrder)
.Select(co => co.Item)
.ToList();

EF Code first Eager loading and OrderBy problem

I have two entities called Category and Product with 1:n relation.
I want to get a Category with its childs that childs be in order.
This is my linq:
_db.Categories.Where(c => c.CategoryID == catID)
.Include(c => c.Products.OrderBy(p => p.ProductID))
.SingleOrDefault();
This query enforce with the below exception because of orderby.
The Include path expression must refer
to a navigation property defined on
the type. Use dotted paths for
reference navigation properties and
the Select operator for collection
navigation properties. Parameter name:
path
Eager loaded data cannot be ordered or filtered. That is linq-to-entities limitation and the only way how to order relations in the database is by using projection:
var data = _db.Polls
.Where(c => c.CategoryID == pollID)
.Select(c => new
{
Pool = c,
Products = c.Products.OrderBy(p => p.ProductID)
})
.SingelOrDefault();
You can project to anonymous or custom type but you cannot project to mapped type (for example Poll).
Another way is dividing this to two queries and use explicit loading:
var poll = _db.Polls.SingleOrDefault(c => c.CategoryID == pollID);
_db.Entry(poll).Collection(c => c.Products)
.Query()
.OrderBy(p =>.ProductID)
.Load();
Include has to reference a navigation property, which means you can't include an OrderBy(). Instead of this:
_db.Categories
.Where(c => c.CategoryID == catID)
.Include(c => c.Products.OrderBy(p => p.ProductID))
.SingleOrDefault();
...you'll have to use this:
_db.Categories
.Where(c => c.CategoryID == catID)
.Include(c => c.Products)
.SingleOrDefault();
...to access an ordered list of Products for each Category, you could add a property to Category like this:
class Category
{
public IEnumerable<Product> OrderedProducts
{
get { return this.Products.OrderBy(p => p.ProductID); }
}
}

Resources