简体   繁体   中英

how to set up models and dbcontext correctly for a one-many LINQ join

consider this:

company model:

public int id { get; set; }
public string name{ get; set; }

report model:

public int id { get; set; }
public string title { get; set; }

company2report (where one company can have many reports):

public int id { get; set; }
public int companyID { get; set; }
public int reportID{ get; set; }
public int sortorder{ get; set; }

where dbcontext is:

public DbSet<company> companies { get; set; }
public DbSet<report> reports { get; set; }
public DbSet<company2report> company2reports { get; set; }

if i wanted to join this in sql it is simply:

SELECT *
FROM   companies as c
INNER JOIN company2reports as c2r ON c.id = c2r.companyID
INNER JOIN reports as r ON c2r.reportID = r.id
ORDER BY c2r.sortorder ASC

so here is my linq

    var q = (from c in db.companies
              join c2r in db.company2reports on c.id equals c2r.companyID
              join r in db.hreports on c2r.reportID equals r.id
              orderby c2r.sortorder
              select new {
                     c.id, c.name,
                     r.id, r.title
                 });

which is all great except this fails
the sql which is generated looks like this:

SELECT c.id, c.name, r.id, r.title
FROM   companies as c
INNER JOIN company2report as c2r ON c.id = c2r.companyID
INNER JOIN reports as r ON c2r.reportID = r.id
ORDER BY c2r.sortorder ASC

(see the first join on 3rd line) it generates COMPANY2REPORT rather than COMPANY2REPORTS

so then i tried adjusting the c2r model to look like this:

public int id { get; set; }
public int companyID { get; set; }
public int reportID{ get; set; }
public ICollection<report> reports { get; set; }
public int sortorder{ get; set; }

which made it worse
how do i get my models to work with my context and then to work with the join?

----------------------------------------------------------------
UPDATE:
the answer supplied below is correct
but i wanted to clarify on a theoretical level:
it is because i was mixing my modes with relational db Fkeys vs. object association

in the end i chose to go with object association
i adjusted my models and code to look like this:

company model:

public class company
{
    public int id { get; set; }
    public string name { get; set; }

    // navigation properties
    public ICollection<report> reports { get; private set; }
}

report model:

public class report
{
    public int id { get; set; }
    public string title { get; set; }
    public int companyId { get; set; }
    public short sortorder { get; set; }

    // navigation properties
    public virtual company company { get; set; }
}

company2report DELETED

dbcontext:

    public DbSet<company> companies { get; set; }
    public DbSet<report> reports { get; set; }
    //public DbSet<company2report> company2reports { get; set; }

linq:

        var q = from c in db.companies
                join r in db.reports on c.id equals r.companyId
                where c.id == 4
                orderby r.sortorder
                select r;

If you want to create an one-to-many relationship between those two entities your model would be like this:

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Report> Reports { get; set; }
}

public class Report
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int? CompanyId { get; set; }
    public Company Company { get; set; }
}

A company has many reports, each with one company. That relationship is represented as follows:

protected override void OnModelCreating(Modelbuilder modelBuilder)
{
    modelBuilder.Entity<Company>()
        .HasMany(c => c.Reports)
        .WithOne(e => e.Company);
}

It can also be configured by starting with the other end of the relationship:

protected override void OnModelCreating(Modelbuilder modelBuilder)
{
    modelBuilder.Entity<Report>()
        .HasOne(e => e.Company)
        .WithMany(c => c.Reports);
}

And dbContext

public class SampleContext : DbContext
{
    public DbSet<Company> Companies { get; set; }
    public DbSet<Report> Reports { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM