简体   繁体   中英

Entity Framework Include Parent Entities

When I am accessing all cities my code is like this.

 public IQueryable<City> GetAll()
    {
        var result = from s in this.Context.Cities.Include("States.Countries") select s;
        return result;
    }

This is working fine and including states and countires. I want to get cities by Country Id, below is my code. In the below code, I want to include States.Countires for each city. How can i do this ?

public IEnumerable<City> GetByCountriesId(int Id)
    {
        var result = from s in this.Context.Countries
                     join a in this.Context.States on s.Id equals a.Country_Id
                     join b in this.Context.Cities on a.Id equals b.States_Id
                     where s.Id == Id 
                     select b;

        return result;
    }

Are you sure a city could belong to several states? IMHO you should have a one to many relationship, where an State could have several Cities and a City should belong to one State . The same happens with State and Country . I think you have pluralized those nav. property names ( States in City and Cities in Country ) but there are not collections. In case you have those two one to many relationships in the same way that I describe above, you can write a query as I show as follow to achieve what you need:

 var result = this.Context.Cities.Include(c=>c.State.Country).Where(c=>c.State.Country.Id==Id‌​);

Is better use the DbExtensions.Include extension method because is strongly typed.

Now, maybe you can think this query could end with a NullReferenceException due to the c.State.Country.Id expression in case one of those nav. properties could be null .But that is not going to happen because you need to set those navigation properties (or the FK properties in case that already exist in DB) when you need to save a new City or State in DB, in other word, they are required .

If you use Fluent Api to configure those relationships you will end with something like this:

modelBuilder.Entity<City>().HasRequired(c=>c.State).WithMany(s=>s.Cities).HasForeignKey(c=>c.State_Id);
modelBuilder.Entity<State>().HasRequired(s=>s.Country).WithMany(c=>c.States).HasForeignKey(s=>s.Country_Id);
public IEnumerable<City> GetByCountriesId(int id)
{
    return from country in this.Context.Countries
           where country.Id == id
           from state in country.States
           from c in this.Context.Cities.Include(c => c.States.Select(s => s.Countries))
           where c.States.Any(s => s == state)
           select c;
}

or, even better:

public IEnumerable<City> GetByCountryId(int id)
{
    return from c in this.Context.Cities
                     .Include(c => c.States.Select(s => s.Countries))
           where c.States.Any(s => s.Countries.Any(c => c.Id == id))
           select c;
}

However – while it's clear why Country has a States collection and State has a Cities collection – why does your City have a States collection and your State have a Countries collection? Shouldn't these be State and Country properties, respectively?

Assuming your City really does have a single State , and your State has a single Country , this simplifies it a lot:

return from c in this.Context.Cities
                 .Include(c => c.State.Select(s => s.Country))
       where c.State.Country.Id == id
       select c;

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