简体   繁体   中英

Entity framework `AsNoTracking` is not working with anonymous projection

In the below snipped i try to fetch data using Anonymous Projection and i would like do not track the entities that is fetched.

Note : i have already gone through existing stack question,yet unable to find a working solution for me

using (var db = new Entities())
{
     db.Configuration.LazyLoadingEnabled = false;
     db.Configuration.ProxyCreationEnabled = false;

     var myprojection = db.Table1
                        .AsNoTracking()
                        .Include(gh=>gh.Table2) //Update
                        .Include(gh=>gh.Table3) //Update
                        .Select(x => new
                        {
                            table1= x,
                            table2= x.Table2.Where(g => Some Condition),

                            table3= x.Table3.Where(g=>Some Condition)
                        })
                        .ToList();

    var result = myprojection.Select(g =>g.table1).FirstOrDefault();

}

When i use AsNoTracking() data from the inner tables (table2,3) is lost during the conversion at this line var result = myprojection.Select(g =>g.table1).FirstOrDefault();

Edit

If i remove AsNoTracking() everything works fine.

1) How to use projection and AsNoTracking in entity framework correctly ?

2) Any other option to remove tracking of this query?

Is there any possible workarounds?

First of all, it does not make sense to use db.Configuration.ProxyCreationEnabled = false and AsNoTracking() at the same time.

If you use db.Configuration.ProxyCreationEnabled = false change tracking will turn off for all queries.

But your problem with inner tables 2 and 3 is not caused by AsNoTracking() .

db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false; 

Turn off lazy loading and i guess it's good for performance reason. If turn it on, you will get expected result, but Entity Framework will make additional SQL query to Data Base for every row in myprojection result. You should better do the following:

using (var db = new Entities())
{
   db.Configuration.LazyLoadingEnabled = false;
   db.Configuration.ProxyCreationEnabled = false;

   var myprojection = db.Table1
                    .Include(x=>x.Table2).Include(x=>x.Table3)
                    .Select(x => new
                    {
                        table1= x,
                        table2= x.Table2.Where(g => Some Condition),
                        table3= x.Table3.Where(g=>Some Condition)
                    })
                    .ToList();

  var result = myprojection.Select(g =>g.table1).FirstOrDefault();

}

Using .Include(x=>x.Table2).Include(x=>x.Table3) in your query will force Entity Framerwork to load related Table2 and Table3 for one query to Data Base.

Use ToList() for your navigation properties. Note that it will still projekt in the DB. ( EF6 )

// ..
table2 = x.Table2.Where(g => Some Condition).ToList(),

Update:

With EF4 you probably need to map table2 manually:

 table2 = x.Table2.Where(g => CONDITION).Select(x => new {Foo = x.Bar}),

Maybe you can try like this:

using (var db = new Entities())
    {
         db.Configuration.LazyLoadingEnabled = false;
         db.Configuration.ProxyCreationEnabled = false;

         var myprojection = db.Table1 
                            //.AsNoTracking()  //remove.AsNoTracking() from here
                            .Select(x => new
                            {
                                table1= x,
                                table2= x.Table2.Where(g => Some Condition),
                                table3= x.Table3.Where(g=>Some Condition)
                            })
                            .AsNoTracking()//add .AsNoTracking() here
                            .ToList();    

        var result = myprojection.Select(g =>g.table1).FirstOrDefault();    
    }

NOTE: I dont try this. Just an idea, i hope this helps to you

When i useAsNoTracking() data from the inner tables (table2,3) is lost during the conversion at this line var result = myprojection.Select(g =>g.table1).FirstOrDefault();

Your selecting Table1, into an anonymous type you will not have access to table2 or table3 although the navigation properties are they they will not map. Entities loses it relationships when you select into anonymous type you need to select table two and three or don't pull it into an anonymous type.

Just put your wheres directly in the table one where and then make your call

 var myprojection = db.Table1.Join(db.Table2.Where(x => yourcondition), 
                                     t1 => t1.id, t2 => t2.t1id, (t1, t2) => t1 );

then you have to do another join for table3

but your probably better just making the call in two queries

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