【问题标题】:LINQ: Is there a way to combine these queries into one?LINQ:有没有办法将这些查询合并为一个?
【发布时间】:2015-03-10 04:33:36
【问题描述】:

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

  • 电话
  • 电话列表
  • 电话条件

PhoneListings 具有来自 Phones 表 (PhoneID) 的 FK,以及来自 Phone Conditions 表 (conditionID) 的 FK

我正在开发一个函数,该函数将电话列表添加到用户的购物车,并返回用户的所有必要信息。电话品牌和型号包含在 PHONES 表中,有关 Condition 的详细信息包含在 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();

}

【问题讨论】:

  • 你合并的理由是什么?
  • 只是这样我就可以从一个对象中获取我需要的所有信息,而不必参考三个不同的对象。可能有点矫枉过正,但我​​认为学习如何做到这一点是值得的。

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


【解决方案1】:

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

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 Single 和 SingleOrDefault 扩展重载,它们将谓词作为参数,这将有助于稍微减少代码。

编辑

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

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

这将返回phoneListingWithAssociations中的实体图

(假设外键 PhoneListing.phonePageID => Phones.phoneId 和 PhoneCondition.conditionID => PhoneListing.phonelistingID)

【讨论】:

    【解决方案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,因为如果存在多个元素,则 single 会引发错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      • 1970-01-01
      • 2014-08-04
      • 2022-11-24
      • 2013-01-01
      • 1970-01-01
      • 2011-05-05
      相关资源
      最近更新 更多