ADO Entity hierarchical self referencing - entity-framework

I have a self referencing table named categories that has a parentcategoryid column that is nullable.
When I added the table to the entity designer it created two navigation properties for this relationship and I named one ParentCategory (the zero or 1 nav prop) and the other I named SubCategories (the * many nav prop).
Everything works great except when I go more than one level deep it doesn't pick up the deeper levels.
So I get all the Category.SubCategories but I don't get the categories under the subcategories.
Am I missing something? starting to think I should have stuck with NHibernate. Shouldn't the deeper levels get lazy loaded?
return from c in _entities.ContentCategorySet.Include("SubCategories")
where c.ParentCategory == null
orderby c.Importance, c.Title
select c;

That's how I would Imagine the SubCategories property to behave.
Level 1
++ Level 2
++ Level 2
++ ++ Level 3
Where SubCategories property of Level 1 only returns Level 2 items. Then to get to Level 3 you would access the consecutive Level 2 items, in a recursive method.

OK, At least part of the problem is
where c.ParentCategory == null
When I remove that I get the deeper levels but then have subcategories on the top level. I guess I can just filter them out after the fact.

Related

How can I recursively retrieve a hierarchy of records using EF Core?

I am using EF Core 2.1. I have a Group object that has the following properties:
int GroupId
int? ParentGroupId
Group ParentGroup
The object references the GroupId of its parent using the ParentGroupId property. The depth of the hierarchy is not known when querying. How can I retrieve the entire hierarchy?
I've tried the following, which will get me three levels deep, but how can I get all levels of the hierarchy without knowing the depth? Do I need to rely on a stored proc?
var group = await _membershipDbContext.Groups
.Include(g => g.ParentGroup)
.ThenInclude(g => g.ParentGroup)
.SingleOrDefaultAsync(g => g.GroupId == id);
You have three options:
Use lazy loading. This way every time you'll access the parent group, it will automatically loaded from the database.
Use explicit loading for recursively load the parent groups (see explicit loading)
Create a view or stored procedure in the database that will return all the data you need and then create the object graph manually.
Which method is right for you depends on your unique use-case and the amount of data to load.
Options 1 and 2 are not that different from each other, but with option 2 you control when the objects are loaded. Option 3 will probably be the most efficient, but might pose problems when saving back changes (as you transform the object graph manually).

JPQL query: Item that belongs to multiple categories

Having an entity Items that have a collection field called categories, I need to find items that belong at least to two specific categories, but I cant find the way to build the correct JPQL query.
#Entity
public class Items {
#ManyToMany (fetch = FetchType.EAGER)
private List<Category> categories;
}
I can find an item that have one category:
SELECT i FROM Item i WHERE :cat MEMBER OF item.categories
I can select items with any of several categories:
SELECT i FROM Item i WHERE :cat1 MEMBER OF item.categories OR :cat MEMBER OF item.categories
But when I try to select for items that have at least two specific categories, the following query gets no items:
SELECT i FROM Item i WHERE :cat1 MEMBER OF item.categories AND :cat2 MEMBER OF item.categories
Which is the correct way to do that?
Best regards,
Pablo.
That problem happened to me with ObjectDB.
I have contacted them too, and this was the answer:
This seems to be the result of how JPQL queries are converted into SQL
like syntax before executing. MEMBER OF is implemented using JOIN with
a new synthetic variable for iteration over the collection. In your
query item.categories appears twice, but the same synthetic variable for
iterating over that collection is used for both occurrences, and that
variable cannot match both sides of the AND with the same value.
Possibly we may have to use separate iteration per MEMBER OF as the
results as demonstrated by your post seem unacceptable (although JQPL
itself has strange behaviour in some known cases due to the conversion
to JOIN). However, using separate variables may sometimes make the
query more complex and slow unnecessarily (e.g. for the OR query in
your post), so any change requires careful planning.
As a quick solution, you may replace AND of MEMBER OF with 2 explicit
JOIN variables for iteration over the collection with 2 independent
variables.
So, the solution is to use the following query:
SELECT DISTINCT item
FROM Item item JOIN item.categories cat1 JOIN item.categories cat2
WHERE cat1 = :cat1 AND cat2 = :cat2
I don't know if this a problem only for this specific JPA implementation (ObjectDB).
Anyway, if anybody has a similar problem, I hope that this post can help.

Entity Framework condition for bool to seperate active and inactive into classes not working

I am trying to do the following:
Map a class->Applicants to 2 subclasses ->ActiveApps and InactiveApps in Entity Framework 5.
The field in Applicants is a BIt mapped to a Boolean (IsActive);
I subclass the ActiveApps from Applicants and InactiveApps from Applicants.
I set a condition on both of them :
IsActive = True
IsActive =False
I have tried moving the IsActive column, deleting it, changing to =1 or 0 respectively.
I keep getting all kinds of error messages (though it still compiles).
Does anyone know how to do to set a condition for a boolean without actually getting errors on build?
I can fix this but it is too ugly for practical use. If you add any new entities to EDMX then it goes haywire.
What you do:
Set condition BoolField=0
Then
Add default to Schema section for the scalar conditional item if there is none
Remove condition column from Conceptual model of subclass
Remove column from EntityTypeMapping of parent
Basic Take Home Message: Not quite ready for primetime in EF 5, imho.
You are better off just using views and not getting the inheritance.

Entity Framework, Computed Entity Field

Is it possible to include a computed field in an EF entity? Example, lets say I have a shop selling products, and the products are grouped into categories.
When the list of categories is displayed for editing to the administrator of the shop I wish to list the number of products in each category as part of the list.
In NHibernate I would use a formula e.g.
<property name="Products" formula="dbo.Category_NumProducts(id)" />
I can't work out if something similar is possible for EF. I know I could make a category view and map this to a second entity but that seems wrong as its almost a complete duplication.
EDIT: If this isn't possible in EF, then what is the best way to accomplish this?
Unfortunately if your Category table doesn't have this as computed column you will not be able to map it without creating second entity - it leads to database view, defining query in EDMX or perhaps Query view in EDMX (but Query view may not work because you require aggregate function to be computed).
Edit:
IMHO the simplest solution (and also the best) is simply creating a ViewModel (some non mapped class) and use projection in Linq query:
var query = from c in context.Categories
where ...
select new CategoryView {
Id = c.Id,
Name = c.Name,
...
Products = c.Products.Count()
};

Entity Framework 4: Can you duplicate an entity and alter it based on filter condition

Is there a way within the entity framework designer to duplicate an entity and then apply a filter condition to both to make them unique. Id like to retain all navigation properties and what not.
For example, say in the database I had a table of orders. I could have two entities, one called IncompleteOrders and One called Complete based on the same table, with the complete having a filter specified on the database field 'complete'.
Thanks in advance
Yes, this is called Table per Hierachy
You have one physical table, which has a special, single, scalar column which is used as a discriminator.
Like this:
OrderId OrderName IsComplete
1 Foo 1
2 Bar 1
3 FooBar 0
Where IsComplete is the discriminator (BIT column, for example), so when you setup your entities on your EDMX, you create three entities:
1. Orders
2. CompleteOrders (derives from Orders)
3. InCompleteOrders (derives from Orders)
On the table mapping for Orders, you say "Maps to CompleteOrders, when IsComplete = 1", and "Maps to InCompleteOrders, when OrderType = 0".
Good writeup on TPH/Discriminator pattern here.