Reputation: 33
My problem is accessing related entities in Web App on 2nd level relation. Didn't find proper answer related to EF7.
Let's take following sample of 3 classes: one-to-many - x - many-to-one.
public class Person {
public int PersonId { get; set; }
public string Name { get; set; }
public virtual ICollection<Buy> Buys { get; set; } = new List<Buy>();
}
public class Buy {
public int BuyId { get; set; }
public int PersonId { get; set; }
public int BookId { get; set; }
public virtual Person Person { get; set; }
public virtual Book Book { get; set; }
}
public class Book {
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Buy> Buys { get; set; } = new List<Buy>();
}
With context.
public class MyContext : DbContext {
public DbSet<Person> People { get; set; }
public DbSet<Book> Books { get; set; }
public DbSet<Buy> Buys { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Entity<Person>()
.Collection(c => c.Buys).InverseReference(c => c.Person)
.ForeignKey(c => c.PersonId);
modelBuilder.Entity<Book>()
.Collection(i => i.Buys).InverseReference(i => i.Book)
.ForeignKey(i => i.BookId);
}
Person Controller - Details view.
// _context present in given scope
public IActionResult Details(int? id) {
var person = _context.People
.Include(c => c.Buys)
.Where(c => c.PersonId == id)
.FirstOrDefault();
}
With this configuration I intended to be able to fetch from Person model, not only Buys info, but also related further books. Like following in part of View.
@model <project>.Models.Person
// (...)
@Html.DisplayFor(model => model.PersonId) // ok - person
@Html.DisplayFor(model => model.PersonName) // ok - person
@foreach (var item in Model.Buys) {
@Html.DisplayFor(modeItem => item.BuyId) // ok - buy
@Html.DisplayFor(modelItem => item.Book.Name) // null - book
}
Do I need to code additional references in fluent API or do further includes in entity model to be able to access Item data from Person level?
Upvotes: 2
Views: 180
Reputation: 12491
You should include Book
like you did with Buys
. I mean:
var person = _context.People
.Include(c => c.Buys.Select(x => x.Book))
.Where(c => c.PersonId == id)
.FirstOrDefault();
But actually if you working with MVC it's better to create ViewModel
Class that have all data that you need on particular View rather than have your EF classes on View.
Upvotes: 2
Reputation: 39376
In EF 7 beta7 you can also use the ThenInclude
method to include several levels:
var person = _context.People
.Include(c => c.Buys)
.ThenInclude(b=>b.Book)
.FirstOrDefault(c => c.PersonId == id);
Upvotes: 0