baftinho
baftinho

Reputation: 33

Entity Framework 7 - accessing related entities

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

Answers (2)

teo van kot
teo van kot

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

ocuenca
ocuenca

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

Related Questions