Hey all!
I find EFCore a super powerful framework! I am using it on a private project, where I have 1-n relationships between tables. Unfortunately I can not something worked, I also tried to look for solutions over the internet, and I also checked the official Microsoft website, I am following the examples but still not working. Let me break my issue down four you.
FIrst of all I have a BaseEntity which is extended by the other domain objects:
```c#
public class BaseEntity
{
public int Id { get; set; }
}
Second of all I have a Container table which has several property and three foreign keys, as follows:
```c#
public class Container : BaseEntity
{
public int Size { get; set; }
public string Type { get; set; }
public DateTime LayDownDate { get; set; } //format in table > 2013-08-30 19:05:00
public DateTime DesiredTakeUpDate { get; set; }
public DateTime ContainerRegistered { get; set; }
public int NumberOfTurns { get; set; }
public string Others { get; set; }
public int LocationId { get; set; }
public Location Location { get; set; }
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public int TruckDriverId { get; set; }
public TruckDriver TruckDriver { get; set; }
}
As you can see the foreign keys are: LocationId, CustomerId, TruckDriverId.
As for this issue I am going to show only one of them, since the relation type is same for any, so the solution would be also same, i guess...
So the LocationId looks like the following:
```c#
public class Location : BaseEntity
{
public double Latitude { get; set; }
public double Longitude { get; set; }
public ICollection<Container> Containers { get; set; }
}
Let's see how I set up the connections between the tables with the FluentAP in my DBContext:
```c#
public class ContainersContext : DbContext
{
...
public DbSet<Location> Location { get; set; }
...
public ContainersContext(){}
public ContainersContext(DbContextOptions<ContainersContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Location>()
.HasMany(c => c.Containers)
.WithOne(e => e.Location);
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("...");
}
Well, the issue is the following: Firstly I filled my database with data, so I have some locations and containers where I filled the locationIds correspondingly. When I try to retrieve the containers from the database, I got every information instead of the Location object of the Container. It is null. So what I have to do in order to "connect" the location object to proper container, is the following:
```c#
public IActionResult Index()
{
var containers = _containerRepository.GetAll();
containers.ToList().ForEach(c =>
{
c.Location = _locationRepository.GetAll().FirstOrDefault(l => l.Id == c.LocationId);
});
ContainerMapViewModel mapModel = new ContainerMapViewModel(containers);
return View(mapModel);
}
```
As you can see, I loop trough all the containers, and set the location of each of them. It works well but I am quite convinced that the EFCore has some smart solution for it. Or maybe I have found a bug? Thanks in advance for any help! ;)
What you are missing is loading related data. By default EF never loads related data hence navigation properties are null. EF6 had lazy loading feature which loaded the data when navigation was accessed. This feature is currently not in EF Core (see #3797 ). So in the absence you have to load data manually via eager/explicit loading. (eager loading would be better perf in your case).
More information about how to load related data and details of each method is here in docs. https://docs.microsoft.com/en-us/ef/core/querying/related-data
Most helpful comment
What you are missing is loading related data. By default EF never loads related data hence navigation properties are null. EF6 had lazy loading feature which loaded the data when navigation was accessed. This feature is currently not in EF Core (see #3797 ). So in the absence you have to load data manually via eager/explicit loading. (eager loading would be better perf in your case).
More information about how to load related data and details of each method is here in docs. https://docs.microsoft.com/en-us/ef/core/querying/related-data