Auto eager load navigation property in the DbContext - entity-framework

Is there a way to tamper with the DbContext in order to auto eager load a specific Navigation property when the entity is requested in a query? (no lazy loading).
Entity Framework 5
Example:
var supremeEmployee = context.Employees.FirstOrDefault(x => x.EmployeeId == 42);
and the returned model would come back pre-populated with the "Department" navigation property.

Depends on what your model looks like. If you're using interfaces or inheritance you could add a function to your DbContext class with a generic constraint on that type that always includes the navigation property.
In my experience though you're usually better off not doing that, performance wise. I prefer to load into anonymous types just the fields i need in the moment.
In the most basic way you could do this:
public class Department
{
public int Id { get; set; }
}
public class Employee
{
public int Id { get; set; }
public Department Department { get; set; }
}
public class MyContext : DbContext
{
protected DbSet<Employee> Employees { get; set; }
public IQueryable<Employee> LoadEmployees()
{
return Employees.Include(p => p.Department);
}
}

Related

Entity Framework Core Inheritance creating child tables

public class Product
{
public string Name { get; set; }
public int Qty { get; set; }
public decimal Price { get; set; }``
}
public class CartItem : Product
{
public int CartItemId { get; set; }
public string CartId { get; set; }
}
public class OrderLine : Product
{
public int OrderLineId { get; set; }
public int OrderId { get; set; }
}
public class Kititem : Product
{
public int KititemId { get; set; }
public int OrderId { get; set; }
}
public class SampleContext : DbContext
{
public DbSet<CartItem> CartItems { get; set; }
public DbSet<OrderLine> OrderLines { get; set; }
public DbSet<Kititem> Kititems { get; set; }
}
As you can see in this I am not including the parent class Product in the DbContext, and when doing the migrations it creates a table for each derived class with all the properties form the parent class, and it does not create the parent class because is not included in the Dbcontext, for me it was what I was exptecting and is working, and I am happy with it so far
Mi question is if that is a bad practice and maybe I am not using ef core Inheritance the way I can take all the advantages ?
I am confuse and want to start a new project and do it the best way, so I don't have to redo it again
What you are using is called "base class" as opposed to "base entity", i.e. class participating in database model inheritance.
You are not forced to use database inheritance at all. Moreover EF Core currently supports only Table per Hierarchy (TPH) strategy, which is not the best if you have many derived entities with many different properties (because all the data is stored in a single table).
In other words, there is nothing wrong to not use database inheritance. The only benefit of database inheritance is if you need polymorphic queries, i.e. queries that return Products of different types. It's possible to do such queries w/o database inheritance using Union / Concat LINQ operator, but they won't be efficient due to current EF Core lack of translating such queries to SQL, so they always use client evaluation.
Of course this will be improved in some future EF Core version (as well as support for other inheritance strategies), so the main question should be - do you need such queries. If you don't, then your approach of not using database inheritance is just fine. If you do, then decide which is more suitable for your needs - manual Concat or a single table with a lot of columns.

Entity framework Unidirectional Association One to Many

I'm new in Entity Framework and my English is not very good, sorry if i write something wrong. I want to make an unidirectional association in One-to-Many relationship with Entity Framework 6 using the following example:
public class Person
{
public int personId;
public string Name;
.
.
.
//public ICollection<Phone> Phones { get; set; } //I don't want this nav property
}
public class Phone
{
public int phoneId;
public string number;
public Person myPerson { get; set; }
}
In this classes, a Person has many Phone, so a Phone has only a Person (1 to 1...*) but I want to create the navigation property in Phone, not in Person.
How to create this association with Fluent API for mappings?
Use following mapping
modelBuilder.Entity<Phone>().HasRequired(p => p.myPerson).WithMany();
HasRequired configures required relationship for phone (i.e. it's required to have person id)
WithMany() configures relationship to be required:many without navigation property on many side
Consider reading Configuring Relationships with the Fluent API article.
First of all, you need to be more clear on what you want, considering you changed your question in Sergey's answer.
Considering it, this is what your classes will look like (yes, navigation properties inheritance is supported):
public class Person
{
public int personId { get; set; }
public string Name { get; set; }
}
public abstract class Phone
{
public int phoneId { get; set; }
public int personId { get; set; }
public Person myPerson { get; set; }
}
public class PhoneFixedLine : Phone
{ }
public class PhoneCellPhone : Phone
{ }
Obs.: Mind the getters and setters in the Person and Phone classes.
You want an unidirectional mapping with the navigation property in the Phone class.
Since you are mapping derivated classes you need to follow an Inheritance Strategy, see this linkfor more information.
I will be following the TPC strategy where only the concrete classes are mapped.
In the OnModelCreatingMethod do the following:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PhoneFixedLine>().HasRequired(p => p.myPerson).WithMany()
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("FixedPhones");
});
modelBuilder.Entity<PhoneCellPhones>().HasRequired(p => p.myPerson).WithMany()
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("CellPhones");
});
}
You will face an identity problem with this strategy because these two table share the same primary key phoneId, in the link of the Inheritance Strategies there are two ways of dealing with it.

Entity Framework Eager Loading Table-Per-Type Inheritance derived class

Using a table-per-type inheritance model and Entity Framework Code First, I am trying to eager load a list of derived class. Please note that I can't change the model.
I have the following model (overly simplified)
public class Training
{
public string Name { get; set; }
public IList<Person> Persons { get; set; }
}
public abstract class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
[Table("Students")]
public class Student : Person
{
public string StudentNumber { get; set; }
public IList<Training> Trainings { get; set; }
}
[Table("Instructors")]
public class Instructor : Person
{
public DateTime StartingDate { get; set; }
public IList<Training> Trainings { get; set; }
}
I want to query Training by name and eager load all the persons including the derived class (Student and Instructor). Back in April 2011, Tom Dykstra seemed to claim it wasn't possible.
The current version of the Entity Framework doesn't support eager loading for one-to-zero-or-one relationships when the navigation property is on the derived class of a TPH inheritance structure.
Has this changed? I am using EF5.
I don't see why ...
var list = context.Trainings.Include(t => t.Persons)
.Where(t => t.Name == someName)
.ToList();
... shouldn't work. EF should populate the Persons list with concrete Student and Instructor entities.
You neither have a "one-to-zero-or-one relationship" nor is your navigation property (Training.Persons) "on the derived class". So, I think the mentioned limitation does not apply to your model and query.

Entity Framework with Proxy Creation and Lazy Loading disabled is still loading child objects

I'm having some issues with the Entity Framework using POCOs and I hope someone can tell me at a high level if the behaviour I'm seeing is expected or I need to dig deeper into why it's happening.
I have a class Customer and another CustomerType, so Customer has a property Type (of type CustomerType indicating the type) and CustomerType has property Customers which is a collection of Customers (All Customers that have that type) So these are basically the Navigation properties on both ends of an association, resulting in POCO code something like:
public partial class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public int TypeId { get; set; }
public CustomerType Type { get; set; }
}
public partial class CustomerType
{
public CustomerType()
{
this.Customers = new HashSet<CustomerType>();
}
public int Id { get; set; }
public string TypeName { get; set; }
public virtual ICollection<Customer> Customers { get; set; }
}
I have turned off Proxy creation and LazyLoading (i.e. both DbContext.Configuration.ProxyCreationEnabled=false and DbContext.Configuration.LazyLoadingEnabled=false) because they make Serialization a pain.
As expected when I get instances from the Customer set, the Type property on them is null by default.
But if I get instances from the Customer set with a .Include("Type") not only is it loading the Type properties, but it's also loading the children - i.e. the collection of Customers on each of these.
Is this expected?
It is semi expected. The Include extension affects the SQL that is run. Those CustomerTypes that ARE loaded (by virtue of being included in the Customer query) will be built into the object tree according to the CustomerType.ParentId column.
So if by some fluke both a parent and a child is loaded in the same query, the child will be stuffed into the parent.

IEnumerable in lazy-loading EF

I have two models in EF Code First:
public class Book
{
public int Id { get; set; }
public virtual IEnumerable<Page> Pages { get; set; }
}
public class Page
{
public int Id { get; set; }
public int BookId { get; set; }
public Book Book { get; set; }
}
When loads a Book model from DB, Pages property is Null. But when replace IEnumerable => ICollection, lazy loading works and Pages fills from DB. How use IEnumerable and lazy loading together?
IEnumerable is immutable collection which you cannot modify (add or remove). EF does not support this type because internally EF need to modify collection in model.
Use ICollection instead, ICollection inherits from IEnumerable so it not only still get deferred execution (lazy loading) purpose but also has more methods to modify collection.