实体框架“AsNoTracking”无法使用匿名投影

时间:2016-02-08 13:46:33

标签: c# .net entity-framework linq anonymous

在下面的剪辑中,我尝试使用Anonymous Projection获取数据,我希望不跟踪所提取的entities

注意:我已经解决了现有的堆栈问题,但无法为我找到有效的解决方案

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();

}
  

当我使用内部表格中的AsNoTracking()数据(表格2,3)时,在此行的转换过程中会丢失var result = myprojection.Select(g =>g.table1).FirstOrDefault();

修改

  

如果我删除AsNoTracking(),一切正常。

1)如何正确使用实体框架中的projectionAsNoTracking

2)是否有其他选项可以删除此查询的跟踪?

有没有可行的解决方法?

4 个答案:

答案 0 :(得分:1)

  

首先,使用起来没有意义   db.Configuration.ProxyCreationEnabled = falseAsNoTracking()   在同一时间。

如果您使用db.Configuration.ProxyCreationEnabled = false更改跟踪将关闭所有查询。

但是内部表2和3的问题不是由AsNoTracking()引起的。

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

关闭延迟加载,我认为这对性能原因有好处。如果打开它,您将获得预期的结果,但实体框架将为 myprojection 结果中的每一行向Data Base进行额外的SQL查询。您应该更好地执行以下操作:

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();

}
  

在您的查询中使用.Include(x=>x.Table2).Include(x=>x.Table3)即可   强制实体Framerwork加载相关的Table2和Table3   查询数据库。

答案 1 :(得分:1)

使用ToList()作为导航属性。请注意,它仍将在数据库中生成。 (的 EF6

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

更新

使用 EF4 ,您可能需要手动映射table2

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

答案 2 :(得分:0)

也许你可以尝试这样:

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();    
    }

注意:我不试试这个。只是一个想法,我希望这对你有帮助

答案 3 :(得分:0)

  

当我使用AsNoTracking()来自内部表(table2,3)的数据在此行的转换过程中丢失var result = myprojection.Select(g => g.table1).FirstOrDefault();

您选择Table1,进入匿名类型,您将无法访问table2或table3,尽管导航属性是他们不会映射的。当您选择匿名类型时,实体会失去关系,您需要选择第二和第三表,或者不要将其拉入匿名类型。

将你的小伙子直接放在桌子上,然后拨打电话

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

然后你必须为table3做另一个连接

但你最好只在两个查询中进行调用