LINQ:有没有办法将这些查询合并为一个?

时间:2015-03-10 04:33:37

标签: c# asp.net sql-server asp.net-mvc linq

我有一个包含3个表的数据库:

  • 电话
  • 电话列表
  • PhoneConditions

PhoneListings在电话表(PhoneID)中有一个FK,在电话条件表中有一个FK(conditionID)

我正在开发一个功能,可以将电话清单添加到用户的购物车中,并返回用户的所有必要信息。电话品牌和型号包含在PHONES表中,有关条件的详细信息包含在PhoneConditions表中。

目前我使用3个查询来获取所有必要信息。有没有办法将所有这些组合成一个查询?

public ActionResult phoneAdd(int listingID, int qty)
{

    ShoppingBasket myBasket = new ShoppingBasket();
    string BasketID = myBasket.GetBasketID(this.HttpContext);



     var PhoneListingQuery = (from x in myDB.phoneListings
                             where x.phonelistingID == listingID
                             select x).Single();

     var PhoneCondition = myDB.phoneConditions
                          .Where(x => x.conditionID == PhoneListingQuery.phonelistingID).Single();

    var PhoneDataQuery = (from ph in myDB.Phones
                          where ph.PhoneID == PhoneListingQuery.phonePageID
                          select ph).SingleOrDefault();

}

2 个答案:

答案 0 :(得分:5)

您可以将结果投影到匿名类或元组,甚至是单行中的自定义形状实体,但整体数据库性能可能不会更好:

var phoneObjects = myDB.phoneListings
       .Where(pl => pl.phonelistingID == listingID)
       .Select(pl => new 
       {
          PhoneListingQuery = pl,
          PhoneCondition = myDB.phoneConditions
             .Single(pc => pc.conditionID == pl.phonelistingID),
          PhoneDataQuery = myDB.Phones
             .SingleOrDefault(ph => ph.PhoneID == pl.phonePageID)
       })
       .Single();

  // Access phoneObjects.PhoneListingQuery / PhoneCondition / PhoneDataQuery as needed

LINQ SingleSingleOrDefault扩展还有一些紧凑的重载,它将谓词作为参数,这将有助于略微减少代码。

修改

作为从ORM DbContext进行多次检索或执行明确的手动Join的替代方法,如果您通过可导航的连接键在模型中的实体之间设置navigation relationships(通常在基础表中的外键),您可以使用Include指定使用预先加载的提取深度:

var phoneListingWithAssociations = myDB.phoneListings
       .Include(pl => pl.PhoneConditions)
       .Include(pl => pl.Phones)
       .Single(pl => pl.phonelistingID == listingID);

将返回phoneListingWithAssociations中的实体图

(假设外键PhoneListing.phonePageID => Phones.phoneIdPhoneCondition.conditionID => PhoneListing.phonelistingID

答案 1 :(得分:2)

我认为你应该可以在一个查询中使用join来完成所有操作。

但正如所指出的那样,你可能无法从中获得很多速度,因为你只是选择第一场比赛然后继续前进,而不是真正做任何内部比较。

如果您知道每个表中至少存在一个数据点,那么您也可以同时拉出所有数据点。如果没有那么等待“子查询”就像StuartLC所做的一样好。

 var Phone = (from a in myDB.phoneListings
         join b in myDB.phoneConditions on a.phonelistingID equals b.conditionID 
         join c in ph in myDB.Phones on a.phonePageID equals c.PhoneID
         where 
         a.phonelistingID == listingID
         select new {
         Listing = a,
         Condition = b,
         Data = c
         }).FirstOrDefault();

FirstOrDefault,因为如果存在多个元素,则单个抛出错误。