Entity Framework Core get entity without related entities - c#

I've been searching a bit on this but thus far haven't been able to find a decent solution. I'm trying to get an entity from my database without the related entities attached to it.
The function goes as following return context.Entity.SingleOrDefault(n => n.Name == name) where context is a DbContext.
As of now the reply contains only one Entity but with an added 50 "child" entities which I do not need.
What would be the best way to go about getting a single entity from the db?
Using EFC2.1 pre release build
Edit:
Also found that if you use DbContext.Entity.AsNoTracking you can get the entity without the child collections.
Not sure if the full entity will be saved after making changes and calling DbContext.saveChanges()

You have to enable Lazy Loading, simply add a property to your class like this.
public virtual ICollection<ChildType> NavigationProperty;
Here is a very useful document for Loading Related Data.

I recently discovered that you can also use DbContext.Entity.AsNoTracking() for this purpose.
Using a linq query when fetching an entity will cause all related entities contained in the linq to also be fetched.
Say you have a Teacher, a Student and a Classroom entity. A Teacher can have multiple Students and Classrooms. You want to find all Teachers with classroom A and all male students so you would do
DbContext.Teachers.Where(x => x.Classroom.Name = "A" && x.Student.Gender = "Male")
This will fetch the Teacher entities with all underlying Classrooms and Students since you called on them in the linq expression.
Since you want just the Teacher entity you should use the following :
DbContext.Teachers.AsNoTracking().Where(x => x.Classroom.Name = "A" && x.Student.Gender = "Male")
Using AsNoTracking() you declare that you do not want the underlying data and just need it to filter through the entity you do want.

Related

EF Core: What's the most optimized way to "refetch" an entity in order to get access to FK objects during a creation of a new object?

I want to create a new entity and then aggregate properties on FK objects then save them to the newly created object. Think of populating a keywords field on the object to drive a google like search.
Currently, I've found that the only way to do this is to Add the new entity, call context.SaveChanges(), fetch the newly created entity with all of the include statements, and then use the fetched entity to create the keyword field.
This seems inefficient considering the number of DB hits that need to happen.
Other ORMs have the capability of refetching on save.
What is the most optimized way to handle this in EF Core?
What about this syntax?
context.Entry(blog)
.Collection(b => b.Posts)
.Load();
context.Entry(blog)
.Reference(b => b.Owner)
.Load();
You can load the references onto an existing Entity that way, if I'm understanding the process you're describing correctly.
See the docs for reference
https://learn.microsoft.com/en-us/ef/core/querying/related-data#explicit-loading

Nested relationships never end entity framework

I have 3 tables: Courses, Departments, and Universities.
When I pull the information from the database (using entity framework), I am attempting to map, for example, a Course to a CourseDTO. I am trying to set it up in such a way that the CourseDTO automatically checks if the relationships exist (is not null), then hook up the relationship in the DTO.
Problem is once I run:
db.Courses.Include(c=>c.Department).Include(c=>c.University)
It maps every nested permutation of these relationships, so my automatic mapping to the DTO just creates a stackoverflow because it goes on forever. (eg. Course maps the Department which maps the Courses in that Department, which maps the Department, etc.)
What is the best solution to avoid this problem?
I would suggest turning off Lazy Loading for EntityFramework via
context.Configuration.LazyLoadingEnabled = false
This will prevent the sub-objects that you did not explicitly include from being expanded by Entity Framework when they are accessed.
Either that or create a custom mapping method to include only the objects you want in your DTO.

EF5 ObjectContext : How to replace IQueryable<T>.Include(Path) with context.T.Attach()

I'm using Entity Framework 5 with ObjectContext on a relatively big and complex data model.
I would like to work around big queries generated when chaining multiple IQueryable.Include(Path) to eager load related objects.
For example, I'm doing something like this :
var queryPe = context.Person.Where(p => p.Id == 110).Include(#"AA");
queryPe = queryPe.Include(#"BB.CC.DD");
queryPe = queryPe.Include(#"EE.FF");
It could be made generic by using a string array and chaining each graph at runtime in a foreach loop.
Instead, I would like to do something like this :
Person pe = context.Person.Where(p => p.Id == 110).First();
context.LoadProperty(pe, "AA");
pe.BB.Attach(pe.BB.CreateSourceQuery().Include(#"CC.DD"));
pe.EE.Attach(pe.EE.CreateSourceQuery().Include(#"FF"));
Instead of having one big query we would have 4 smaller queries hitting the database.
Of course I still want to leverage the power of the graph path as a string.
I may be wrong, but this means that I should use relexion to get the navigation properties by name and executing the CreateSourceQuery() on it because there is no such extension method to do this.
Am I correct ?
EDIT 1 : Well, I have an additionnal constraint, that is, I'm using Self Tracking Entities (STE). This means that Related objects are not materialized as EntityCollection or EntityReference. So Attach() and CreateSourceQuery() are not available !
So I'm stuck with Context.LoadProperty to deal with object graphs.
Is it only possible ?
EDIT 2 : Problem exposed in EDIT 1 solved, thanks to the help of DbContext class. See the code below :
Person pe = context.Person.Where(p => p.Id == 110).First();
context.LoadProperty(pe, "AA");
DbContext dbc = new DbContext(context, false);
dbc.Entry(pe).Collection(#"BB").Query().Include(#"CC.DD").Load();
dbc.Entry(pe).Reference(#"EE").Query().Include(#"FF").Load();
EDIT 3 02/11/2013 : There is an issue with the code presented above (EDIT 2). If the last entity in the path is a reference and not a collection, the code doesn't fail but it is not loaded :-(
EDIT 4 : Instead of using reflection, right now, I'm generating the code by looking at the Entity Data Model with the help of a T4 template.
Sometimes stored procedures are best. Write a stored procedure that returns multiple result sets, one for each type of entity you wish to eagerly load. This is highly performant compared to what you're trying to accomplish and the stored procedure will be far more readable than this jumble of includes and separate load statements per reference/collection. And yes, EF will hook up related entities automatically!
Here's a reference for sprocs with multiple result sets for both EDMX and code first:
http://msdn.microsoft.com/en-us/data/jj691402.aspx
Try to separate your aggregates in multiple contexts. Each Bounded context should have a separate context. This way you create a loosely coupled entity framework solution.
Julie Lerman has a good video on plural sight about this concept.
I would prefer to use stored procedures. Easy maintainance, works faster etc.

Why Is A Navigation Property Updating Another Entity When Executing An Update In My DataContext? (C# Entity Framework)

I'm running into a situation using the Entity Framework (EF) that has me totally stumped. I'm doing a simple update and the error I'm getting is
Violation of PRIMARY KEY constraint 'PK__tblProducts_Mark__03E07F87'. Cannot insert duplicate key in object 'healthc.tblProducts_MarketSegmentGroups'.
The statement has been terminated.
Let me give you some background on the problem.
I am using Web Forms and have a button click event fire to save some data in several text box controls on my page.
I have a table in my database called tblMetaProducts, which is a table used to store product information from various vendors we work with. The entity for this table is called Products.
I have another table called tblTechAssessment, which holds data for technical questions about the vendor's product, (e.g. what operating system can the software run on, version number etc.). The entity for this table is called TechnicalAssessment. A product can have many technical assessments and they are related by the product id.
I finally have a lookup table in the database called tblProducts_MarketSegmentGroups, which holds a product id and another id (which we don't care about for this problem). The entity for this table is called ProductMarketSegmentGroup. a product can have many product market segment groups and they are releated by the product id.
Here is the code I'm executing to perform the EF save
private void UpdateTechnicalAssessments(int productID)
{
var technicalAssessments = VendorDirectoryController.GetTechnicalAssessments(productID);
var technicalAssessmentTypes = Enum.GetValues(typeof(TechnicalAssessmentType)).Cast<TechnicalAssessmentType>();
foreach (var technicalAssessmentType in technicalAssessmentTypes)
{
var typeName = technicalAssessmentType.ToString();
var id = "SaveToProduction" + typeName + "TextBox";
var results = ProductInformationPanel.FindDescendantsByType<TextBox>().Single(x => x.ID == id).Text;
technicalAssessments.Single(x => x.QuestionID == (int)technicalAssessmentType).Results = results;
}
VendorDirectoryController.SaveChanges();
}
The SaveChanges() method drills down to my domain layer and calls the dataContext.SaveChanges() method.
So my questions are:
1) What can I do to get this to save my TechnicalAssessment entities?
2) Why does my save affect the ProductMarketSegmentGroup entity?
You might be hitting a bug in EF. I also stubmled on something similar (even though I use stored procedures).
The solution was to apply hotfix mentioned in: hotfix: Principal entity in an SQL application generates unnecessary updates - do it still effect EF 4.3.1?
The solution I ended up using was to have our database admin create a proc for the update. I was never able to figure out why the navigation property was causing such a fuss.

Self join not including children (entity framework 4.0)

I am creating a sort of family tree in entity framework 4.0. I have come across an issue where the Entity Framework is only loading the immediate children. It does not load the children of the children even though i have an include specified.
For example, this is my query :-
public IQueryable<TreeMember> GetTreeMembers(int userId)
{
return this.ObjectContext.TreeMembers.Include("RelatedTreeMembers").Where(u => u.UserId == userId && u.RelatedTreeMemberId == null);
}
This would load the 1st level of children. But it does not load the children of the children. If i have to include children of the children, i have to write :-
public IQueryable<TreeMember> GetTreeMembers(int userId)
{
return this.ObjectContext.TreeMembers.Include("RelatedTreeMembers.RelatedTreeMembers").Where(u => u.UserId == userId && u.RelatedTreeMemberId == null);
}
This is quickly getting to be frustrating because i don't know how many times should i have to write this RelatedTreeMembers as a family tree can extend upto N level. How do i get past this issue? If my question is not clear please let me know.
Thanks in advance :)
That is how EF works. You want to define recursive (hierarchical) query which is not possible with eager loading in EF. You always have specify exactly which navigation properties you want to load - obviously in this scenario you can't because you don't know how deep is your recursion.
I like the idea #Magnus suggested with CTE but I would not use DB View. I would use stored procedure. The reason is that you already have entity TreeMember mapped to a table. If you define the view you will not be able to map it to the same entity type. You will need new entity for the view. If you use stored procedure you can map its result to already existing entity type.
Another way is to use lazy loading.
Write a view with a recursive CTE and than use that with Linq.
http://msdn.microsoft.com/en-us/library/ms186243.aspx

Categories