2012-07-18 63 views
1

我想添加一个新的实体到数据库已经使用EF来检索其他数据实例。我希望能使用如下代码如下:添加到实体框架投影中创建的集合

using (var db = new FundResearchContext(null)) 
{ 
    var query = from a in db.As select new 
       { 
        a = a, 
        bs = (from b in db.Bs where b.AnId == a.AnotherId select b) 
       }; 

    var listOfAsAndRelatedBs = query.ToList(); 
    listOfAsAndRelatedBs[0].bs.Add(new B()); 
    db.SaveChanges(); 
} 

虽然bs集合中的对象进行跟踪,并将其保存更改后,我不能添加新项目的收集,因为它是IQueryable类型。我意识到在这样一个简单的例子中,我可以将属性放在A和B上以表示它们通过外键链接,但是这种方法在我的真实生活场景中不可行。那么是否有一种替代语法可以使bs本身成为一个跟踪对象,我可以添加新的B对象并让它们保持不变?或者我必须使用db.Bs.Add(new B())手动执行所有操作吗?

回答

1

如果您A类有一个Bs收集就可以了,你可以说:

var query = from a in db.As select new 
      { 
       a = a, 
       bs = a.Bs 
      }; 

这有一个不错的急切加载效果,因为当这个查询是马时,所有的B s为每个A加载和附加terialized。您应该可以将对象添加到其中一个结果的bs属性或a.Bs属性中。

如果你没有在你的实体类之间建立这种关系,你将无法做到这一点,并且你会被直接添加到db.Bs。当然,你可以创建一个快捷方式的排序对象,以促进这一点:

public class DTO {public A a{get;set;} public IObjectSet<B> allBs {get;set;} } 

var list = (from a in db.As 
      select new DTO 
      { 
       a = a, 
      }).ToList(); 
foreach(var a in list) 
{ 
    a.allBs = db.Bs; 
} 

你不必访问上下文这种方式直接将项目添加到Bs

+1

您是对的,我没有'Bs'集合在'A'上,我可以用作导航属性。好像我需要直接添加到'db.Bs'并跟踪我添加到不同列表中的对象,而不是匿名投影类中的'bs'属性。 – 2012-07-18 21:16:16

0

如果你打电话ToList()在匿名对象设置bs时,那么bs应该是类型List<B>

using (var db = new FundResearchContext(null)) 
{ 
    var query = from a in db.As select new 
       { 
        // ... 
        bs = (from b in db.Bs 
          where b.AnId == a.AnotherId 
          select b) 
         .ToList() 
       }; 
    // ... 
} 
+2

LINQ to Entities将不允许对像这样的查询内的.ToList()调用。 – StriplingWarrior 2012-07-18 20:53:27

+0

恐怕我已经尝试过了。虽然编译器对此感到满意,但当它执行时,我得到一个System.NotSupportedException异常,其中包含消息“LINQ to Entities does not recognized the method ...” – 2012-07-18 20:58:10