Select only parent data and not child data using Entity Framework - entity-framework

I have lazy loading enabled for a database-first Entity Framework model. For this example, I will use the tables State and City, where the City table is a child table for the State table (connected via a foreign key).
When using the following query:
from State in DBEntity.State
where State.StateId == 1
select State
I get the State object, which includes a List of City objects. This list is populated when using the query above. In some circumstances, I need just the list of States and do not want the Cities. In these cases, getting the child data (cities) would significantly decrease performance. In some other circumstances, I do need all child data even if the performance is slow.
How can I achieve the following:
Get all State and City data in one function
Get just the State data and not the City data (no child data) in another function

Make the City property on State virtual.
Per EntityFrameworkTutorial.net:
Navigation property should be defined as public, virtual. Context will NOT do lazy loading if the property is not defined as virtual.
This will only load the list of City objects if you use an include() statement or attempt to access them after loading your State.

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).

NSFetchResultController: Fill TableView with fetched entity and its related entity

I have 2 entities. One describes the Section of the TableView (A Month its name, etc.) This entity is related with a one to many relationship to another entity which should describe the rows of the TableView.
I'm a bit confused how to get those entites by an NSFetchedResultController. As far as I now I can only fetch one relationship at the time. So which one should I get to fill the table properly?
If you're using NSFetchedResultsController, you fetch the objects you want to display in the table view.
To get sections, you use NSFetchedResultsController's sectionNameKeyPath property to indicate how to find a section name from one of the fetched objects. This key path is something you could pass to one of the fetched objects via valueForKeyPath: to get the section name. In your case it would require traversing a relationship back to the month entity (or whatever it really is) to get its name. For example if the relationship is called month and the Month entity has a name attribute, you would pass something like #"month.name" as the sectionNameKeyPath argument when you create the fetched results controller.
You can also use the excellent Sensible TableView framework to automatically fetch the Core Data objects and display them in a table view. The framework will also detect if the entities have any relationships and will automatically manage the detail view controllers between them.

Is there a way to load only ID of entity/entities avoiding FetchGroup strategy ?

There some cases when loading of only ID of an entity or IDs of a collection of entities (in a relationship, for example) is needed. For example I have en entity Parent and a collection of children in it
class Parent {
private List<Child> children;
}
So, when I want to load children I want only the ids to be loaded for some cases, not whole state of children. I made a research and I found a way via Named FetchGroup, which means if I want to implement this I have to add for each Entity annotation #FetchGroup(name="id", attributes = {#FetchAttribute(name = "id")}). That work for the cases when I want to apply it for only an entity of course. For children case also LoadGroup should be configured.
The question here is: is there another strategy specially for loading of ONLY ID's, when an entity or entities are requested ? Or a way to indicate that ? Here I want to avoid annotation with #FetchGroup all entities I would like to applied that, just for loading of only ID. Of course, creation of a query like "SELECT ID FROM Parent WHERE ..." or "SELECT child.id FROM Parent INNER JOIN Parent.children WHERE ..." is also not a solution here since always should be defined, for all relationships and entities.
If you just want one entity, you can use getReference() on EntityManager.
If it is a query, or relationship, then fetch groups in EclipseLink is your only option.

Select Specific Columns from Database using EF Code First

We have a customer very large table with over 500 columns (i know someone does that!)
Many of these columns are in fact foreign keys to other tables.
We also have the requirement to eager load some of the related tables.
Is there any way in Linq to SQL or Dynamic Linq to specify what columns to be retrieved from the database?
I am looking for a linq statement that actually HAS this effect on the generated SQL Statement:
SELECT Id, Name FROM Book
When we run the reguar query generated by EF, SQL Server throws an error that you have reached the maximum number of columns that can be selected within a query!!!
Any help is much appreciated!
Yes exactly this is the case, the table has 500 columns and is self referencing our tool automatically eager loads the first level relations and this hits the SQL limit on number of columns that can be queried.
I was hoping that I can set to only load limited columns of the related Entities such as Id and Name (which is used in the UI to view the record to user)
I guess the other option is to control what FK columns should be eager loaded. However this still remains problem for tables that has a binary or ntext column which you may not want to load all the times.
Is there a way to hook multiple models (Entities) to the same table in Code First? We tried doing this I think the effort failed miserably.
Yes you can return only subset of columns by using projection:
var result = from x in context.LargeTable
select new { x.Id, x.Name };
The problem: projection and eager loading doesn't work together. Once you start using projections or custom joins you are changing shape of the query and you cannot use Include (EF will ignore it). The only way in such scenario is to manually include relations in the projected result set:
var result = from x in context.LargeTable
select new {
Id = x.Id,
Name = x.Name,
// You can filter or project relations as well
RelatedEnitites = x.SomeRelation.Where(...)
};
You can also project to specific type BUT that specific type must not be mapped (so you cannot for example project to LargeTable entity from my sample). Projection to the mapped entity can be done only on materialized data in Linq-to-objects.
Edit:
There is probably some misunderstanding how EF works. EF works on top of entities - entity is what you have mapped. If you map 500 columns to the entity, EF simply use that entity as you defined it. It means that querying loads entity and persisting saves entity.
Why it works this way? Entity is considered as atomic data structure and its data can be loaded and tracked only once - that is a key feature for ability to correctly persist changes back to the database. It doesn't mean that you should not load only subset of columns if you need it but you should understand that loading subset of columns doesn't define your original entity - it is considered as arbitrary view on data in your entity. This view is not tracked and cannot be persisted back to database without some additional effort (simply because EF doesn't hold any information about the origin of the projection).
EF also place some additional constraints on the ability to map the entity
Each table can be normally mapped only once. Why? Again because mapping table multiple times to different entities can break ability to correctly persist those entities - for example if any non-key column is mapped twice and you load instance of both entities mapped to the same record, which of mapped values will you use during saving changes?
There are two exceptions which allow you mapping table multiple times
Table per hierarchy inheritance - this is a mapping where table can contains records from multiple entity types defined in inheritance hierarchy. Columns mapped to the base entity in the hierarchy must be shared by all entities. Every derived entity type can have its own columns mapped to its specific properties (other entity types have these columns always empty). It is not possible to share column for derived properties among multiple entities. There must also be one additional column called discriminator telling EF which entity type is stored in the record - this columns cannot be mapped as property because it is already mapped as type discriminator.
Table splitting - this is direct solution for the single table mapping limitation. It allows you to split table into multiple entities with some constraints:
There must be one-to-one relation between entities. You have one central entity used to load the core data and all other entities are accessible through navigation properties from this entity. Eager loading, lazy loading and explicit loading works normally.
The relation is real 1-1 so both parts or relation must always exists.
Entities must not share any property except the key - this constraint will solve the initial problem because each modifiable property is mapped only once
Every entity from the split table must have a mapped key property
Insertion requires whole object graph to be populated because other entities can contain mapped required columns
Linq-to-Sql also contains ability to mark a column as lazy loaded but this feature is currently not available in EF - you can vote for that feature.
It leads to your options for optimization
Use projections to get read-only "view" for entity
You can do that in Linq query as I showed in the previous part of this answer
You can create database view and map it as a new "entity"
In EDMX you can also use Defining query or Query view to encapsulate either SQL or ESQL projection in your mapping
Use table splitting
EDMX allows you splitting table to many entities without any problem
Code first allows you splitting table as well but there are some problems when you split table to more than two entities (I think it requires each entity type to have navigation property to all other entity types from split table - that makes it really hard to use).
Create stored procedures that query the number of columns needed and then call the stored procs from code.

Model a 1-to-many relationship with a single table in Entity Framework

Lets say I have 2 tables on my physical model, Receipt(ID, Location) and LineItem(ID, ReceiptID, ItemName) where a Receipt has multiple LineItems and ReceiptID is a Foreign Key to Receipt's ID.
I want to model these as a single table in my conceptual model, where I only see a table of LineItems with the Location included on each LineItem.
Every time I try to model this in the Entity Modeler, I get an error about how the Primary Key must be the same for every table being combined into the single conceptual entity.
Is this even possible to model using the entity framework?
Thanks!
No there is no way to model this directly. You must either create database view and map that view or import both entities and create QueryView in the model. In both cases resulting entity combining your two tables will become readonly and the only way to support CUD operations will be mapping stored procedures.