c# - How to filter "Include" entities in entity framework? -


entities:

    public class room     {         public room()         {             this.reservations = new hashset<reservation>();         }          public int id { get; set; }          public decimal rate { get; set; }          public int hotelid { get; set; }          public virtual hotel hotel { get; set; }          public virtual icollection<reservation> reservations { get; set; }     }      public class hotel     {         public hotel()         {             this.rooms = new hashset<room>();         }          public int id { get; set; }          public string name { get; set; }          public virtual icollection<room> rooms { get; set; }     }      public class reservation     {         public int id { get; set; }          public datetime startdate { get; set; }          public datetime enddate { get; set; }          public string contactname { get; set; }          public int roomid { get; set; }          public virtual room room { get; set; }     }    public class executivesuite : room   {   }    public class datacontext : dbcontext     {         public dbset<hotel> hotels { get; set; }          public dbset<reservation> reservations { get; set; }          public dbset<room> rooms { get; set; }          protected override void onmodelcreating(dbmodelbuilder modelbuilder)         {             modelbuilder.entity<room>()                 .haskey(r => r.id)                 .hasrequired(r => r.hotel)                 .withmany(r => r.rooms)                 .hasforeignkey(r => r.hotelid);              modelbuilder.entity<hotel>()                 .haskey(h => h.id);              modelbuilder.entity<room>()                 .hasmany(r => r.reservations)                 .withrequired(r => r.room)                 .hasforeignkey(r => r.roomid);          }     } 

the client code(console app):

static void main(string[] args)         {             // initialize , seed database             using (var context = new datacontext())             {                 var hotel = new hotel { name = "grand seasons hotel" };                 var r101 = new room { rate = 79.95m, hotel = hotel };                 var es201 = new executivesuite { rate = 179.95m, hotel = hotel };                 var es301 = new executivesuite { rate = 299.95m, hotel = hotel };                  var res1 = new reservation                 {                     startdate = datetime.parse("3/12/2010"),                     enddate = datetime.parse("3/14/2010"),                     contactname = "roberta jones",                     room = es301                 };                 var res2 = new reservation                 {                     startdate = datetime.parse("1/18/2010"),                     enddate = datetime.parse("1/28/2010"),                     contactname = "bill meyers",                     room = es301                 };                 var res3 = new reservation                 {                     startdate = datetime.parse("2/5/2010"),                     enddate = datetime.parse("2/6/2010"),                     contactname = "robin rosen",                     room = r101                 };                  es301.reservations.add(res1);                 es301.reservations.add(res2);                 r101.reservations.add(res3);                  hotel.rooms.add(r101);                 hotel.rooms.add(es201);                 hotel.rooms.add(es301);                  context.hotels.add(hotel);                 context.savechanges();             }              using (var context = new datacontext())             {                 context.configuration.lazyloadingenabled = false;                 // assume have instance of hotel                 var hotel = context.hotels.first();                  // explicit loading load() provides opportunity filter related data                  // obtained include() method                  context.entry(hotel)                        .collection(x => x.rooms)                        .query()                        .include(y => y.reservations)                        .where(y => y executivesuite && y.reservations.any())                        .load();                  console.writeline("executive suites {0} reservations", hotel.name);                  foreach (var room in hotel.rooms)                 {                     console.writeline("\nexecutive suite {0} {1} per night", room.id,                                       room.rate.tostring("c"));                     console.writeline("current reservations are:");                     foreach (var res in room.reservations.orderby(r => r.startdate))                     {                         console.writeline("\t{0} thru {1} ({2})", res.startdate.toshortdatestring(),                                           res.enddate.toshortdatestring(), res.contactname);                     }                 }             }              console.writeline("press <enter> continue...");             console.readline();         }    using ( var context = new datacontext() ) {          //context.configuration.lazyloadingenabled = false;          // assume have instance of hotel         var hotel = context.hotels.first();         var rooms = context.rooms.include( r => r.reservations ).where( r => r executivesuite && r.reservations.any() ).where( r => r.hotel.id == hotel.id );         console.writeline( "executive suites {0} reservations", hotel.name );          foreach ( var room in hotel.rooms )         {            console.writeline( "\nexecutive suite {0} {1} per night", room.id,                              room.rate.tostring( "c" ) );            console.writeline( "current reservations are:" );            foreach ( var res in room.reservations.orderby( r => r.startdate ) )            {               console.writeline( "\t{0} thru {1} ({2})", res.startdate.toshortdatestring(),                                 res.enddate.toshortdatestring(), res.contactname );            }         }      } 

i tried projecting , putting in anonymous object:

       var hotel = context.hotels.select(h =>         new          {                id = h.id,             name = h.name,             rooms = h.rooms.where(r => r.reservations executivesuite && r.reservations.any())         }).first(); 

but exception: "dbisofexpression requires expression argument polymorphic result type compatible type argument."

now, if notice, implemented in 2 different ways, first explicitly loading related entities, second having 2 different queries, question be, there way can load object graph , filter entities "include" single trip database?

thanks.

there 2 way filter include entity.

  • using projection (see @eldho answer)
  • using third party library

disclaimer: i'm owner of project entity framework plus

the ef+ query includefilter allow filter included entities.

context.entry(hotel)        .collection(x => x.rooms)        .query()        .includefilter(y => y.reservations                             .where(z => z executivesuite && z.reservations.any())        .load(); 

under hood, library projection.

wiki: ef+ query include filter

edit: answer subquestion

you did it. rooms included , filtered, didn't include reservations.

var hotel = context.hotels     // include executive suite reservation     .includefilter(x => x.rooms.where(y => y executivesuite && y.reservations.any()))     // include reservation executive suite     .includefilter(x => x.rooms.where(y => y executivesuite).select(z => z.reservations))     .first(); 

Comments

Popular posts from this blog

angular - Is it possible to get native element for formControl? -

unity3d - Rotate an object to face an opposite direction -

javascript - Why jQuery Select box change event is now working? -