Efficiently getting a count of child records when returning parent record(s) - sql

I am using Entity Framework 4.1 using the Code First approach. I have two entities that exhibit a parent-child relationship. To provide a concrete example, imagine I have a Category entity that has zero-to-many Product entities associated with it. I have set up navigation properties on both sides (in my example, the Category entity would have an ICollection<Product> property while the Product entity has a Category property).
Now, when I get Category entities I want to also get back a count of the number of children records for each category. I am aware I can do:
Category category = dbContext.Categories.Single(...);
int productCount = category.Products.Count();
But I am concerned because the resulting SQL that gets sent to the database depends on whether I use lazy or eager loading.
In the first case (lazy loading), the call to the Products collection prompts EF to run a SQL query like:
SELECT ... all columns ...
FROM Products
WHERE CategoryID = #CategoryID
In the second case (eager loading), the products are loaded when the category information is retrieved so there is no second query to the database, but the downside is that if I'm not at all interested in products (other than their count) then I'm bringing back a lot of unneeded data.
What I'd like it to have the best of both worlds: namely, the ability to have just one database query and one that uses SELECT COUNT(*) rather than one that gets all of the columns from the table. In short, I'd like SQL like the following to be sent to the database:
SELECT ... all category columns ...,
(SELECT COUNT(*) FROM Products p WHERE p.CategoryID = c.CategoryID)
FROM Categories c
WHERE c.CategoryID = ...
Is that at all possible with EF or is what I want a pipe dream?

Not sure, but maybe try this:
var result = db.Categories.Where(x => x.CategoryId == categoryId)
.Select(y => new
{
Count = y.Products.Count(),
Category = y
})
.Single();
//result.Count
//result.Category

Yes, this is possible with EF. You can also create a view model to show the information with the child counts as properties. This article cover how to do that.
http://www.ozkary.com/2015/04/entity-framework-associated-table.html

Related

Relations Has Many Through with 3 models - TypeORM

I have three models: User, Category and Feed.
The first one is User and it has a One to Many relationship with the second model which is Category. Category has a userId column and a Many to One relationship with User.
Category has a One To Many relationship with the third and last model: Feed. Similarly, Feed has a column categoryId and a Many To One relationship with Category.
I want to access the Feeds of a certain categoryId (for example of categoryId = 2) but only where the userId on this category is a certain value too (for example of userId = 1).
This relation is the has_many_through for Ruby on Rails programmers...
How can I build this query using TypeORM ?
Alternatively, if you have an idea on how to write it in pure SQL I'll take it too.
I'm also thinking about creating a column userId directly through Feeds to have a One To Many relationship between User and Feed. Do you think it'll be more optimized to do so ?
Many thanks.
This is how you would achieve that through pure SQL, I'm not much help on the TypeORM front unfortunately.
SELECT f.*
FROM Feeds f
LEFT JOIN Category g
ON f.categoryId = g.categoryId
WHERE f.categoryId = 2
AND g.userId = 1

Fluent NHibernate One-to-Many Mapping Results in Bad Query

I have a pretty simple one to many mapping using Fluent NHibernate and it works fine except the the queries NH generates are less than ideal. I found this when I checked the sql log from NH.
The query I am looking for is like
select p.*, c.* from parent p inner join child c on p.Id = c.parentId
where p.ID is the PK of the parent table and c.ParentId is a FK in the child table pointing to the PK of the parent table.
But what I found from the sql log is something like this:
select P.* from Parent
followed by a bunch of queries running against the child table like
select * from child c where c.ParentId = #p0
Not surprisingly this is causing performance issues.
My question is why NH is not generate the inner join query I think it should? What do I need to change so that NH will generate the desired query?
The JOIN is not suitable in this scenario. It will produce SELECT resulting in more rows, then the Parent table has. I.e: each child of a parent will append new row.
The appropriate solution here is to keep these selects separated. Firstly select the parent, then load all children for all parents (just selected parents). NHibernate does have nice solution for this:
19.1.5. Using batch fetching
Fluent version described here: How to Eager Load Associations without duplication in NHibernate?
This would work a bit similar as you experienced. Firstly select parent, then go for child(ren). The biggest difference is, that instead of 1 + N (going for each children collection separately) we now go for more children in batches. so it could be 1 + 2
Examples of the batch size mapping
1) Colleciton
HasMany<Child>(x => x.Children)
.BatchSize(25);
2) Entity itself
public ChildMap()
{
Id(x => x....
...
BatchSize(25);
There are many other advantages, where the PAGING is one of the most profitable. Because we are working with a flat (not multiplied) Parent, we can apply .Take() and .Skip()
Finally, fi we would like to find some Parents based on their children, we can use in this scenario Subqueries: 15.8. Detached queries and subqueries

SQL subquery result in LINQ and Entity Framework Code First

I want to make a query that'll return me entities and additionally a number of one of their associated entities. For example:
select *, (select COUNT(*) from Forms where Contact_Id = Contacts.Id)
as FormsCount from Contacts;
My Contact entity has a property named FormsCount, but it isn't mapped since there's no column named like that in the table. Is it possible to write one LINQ query that'll return me Contact entities with the additional FormsCount property filled in?
Alternatively, I'd be happy if I could get the FormsCount values in a separate field and I can copy them to the entities manually. The result from the query could be in this form for example:
{
Contact Contact;
int FormsCount;
}
Then I can iterate over the results and copy FormsCount to Contact. Maybe this can be achieved by using projections?
I know how to do that using 2 queries:
a) fetch contact entities first
b) fetch pairs or contact ID and FormsCount for contacts returned in the first query.
But I'd like to do that using one query. Also, I don't want the FormsCount property to be always filled in my Contact entity, I want to have a control over that. Any ideas?
Thanks,
Michal
You are right about the projection.
If Contact has a navigation property Forms you can project:
from c in context.Contacts
select new { Contact = c, FormsCount = c.Forms.Count() }
If not, you'll have to use a subquery:
from c in context.Contacts
select new
{
Contact = c,
FormsCount = context.Forms.Count(f => f.Contact_Id == c.Id)
}
EF will handle both situations in one SQL query.

linqpad query to connect two entities in odata

I am using linqpad. I have an ODATA connected. The entities are listed in left pane with relationships. There are two entities called Products and Customers. I have to get all the product id starting with pid and names of all customers startin with b. There is a relationship between both. Product is a child of customer. How do I do? I am trying since two days but unable to figure it out. Anyone could help?
this is the base code. i dont no what to do further.
from p in products
where p.ProductId.StartsWith("Pid")
from c in customers
where c.Name.StartsWith("B")
select new
{
p.Pid,
c.Name
};
Can you please specify how you want the relation between the two entities to affect the result of the query? Do you expect the above to only returns products (with ID starting with a given value) and then only the customers for those products which name starts with a certain value?
Such a query is not expressible in OData unfortunately. You could request all products which ID starts with a specific value, and all the related customers. And then filter the customers on the client.
For example this will get you all the products which ID starts with a certain value and all their customers:
from p in products
where p.ProductId.StartsWith("Pid")
select new Product
{
ProductId = p.ProductId,
Customers = p.Customers
};

Querying a self referencing join with NHibernate Linq

In my application I have a Category domain object. Category has a property Parent (of type category).
So in my NHibernate mapping I have:
<many-to-one name="Parent" column="ParentID"/>
Before I switched to NHibernate I had the ParentId property on my domain model (mapped to the corresponding database column).
This made it easy to query for say all top level categories (ParentID = 0):
where(c => c.ParentId == 0)
However, I have since removed the ParentId property from my domain model (because of NHibernate) so I now have to do the same query (using NHibernate.Linq) like so:
public IList<Category> GetCategories(int parentId) {
if (parentId == 0)
return _catalogRepository.Categories.Where(x => x.Parent == null).ToList();
else
return _catalogRepository.Categories.Where(x => x.Parent.Id == parentId).ToList();
}
The real impact that I can see, is the SQL generated. Instead of a simple 'select x,y,z from categories where parentid = 0' NHibernate generates a left outer join:
SELECT this_.CategoryId as CategoryId4_1_,
this_.ParentID as ParentID4_1_,
this_.Name as Name4_1_,
this_.Slug as Slug4_1_,
parent1_.CategoryId as CategoryId4_0_,
parent1_.ParentID as ParentID4_0_,
parent1_.Name as Name4_0_,
parent1_.Slug as Slug4_0_
FROM Categories this_
left outer join Categories parent1_
on this_.ParentID = parent1_.CategoryId
WHERE this_.ParentID is null
Which doesn't seems much less efficient that what I had before.
Is there a better way of querying these self referencing joins as it's very tempting to drop the ParentID back onto my domain model for this reason.
Thanks
My first reaction would've been: yes - this is the way it is. Without doing anything NHibernate always tries to load the whole element - and this means that it loads the parent element too. Is this really a performance problem or is it just an aesthetical problem ?
And I don't think that including the parent id would help you - because it still would load the parent item with it.
But if you would really like to optimize this read the following article http://www.javalobby.org/java/forums/t20533.html. It is about Hibernate, but it gives you some ideas about how to handle this and a (possible) solution for your problem.