我有一个包含3个表的数据库:
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();
}
答案 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 Single
和SingleOrDefault
扩展还有一些紧凑的重载,它将谓词作为参数,这将有助于略微减少代码。
修改强>
作为从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.phoneId
和
PhoneCondition.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,因为如果存在多个元素,则单个抛出错误。