linq中有多个交叉引用表连接

时间:2014-02-17 22:15:41

标签: c# linq cross-reference

这一直困扰着我一段时间,因为我正在尝试提出一种优化的查询方式。

因此,假设我有3个共享列的交叉引用表,其中该公共列将在包含更多信息的主表上进行最终连接。

例如:

假设我有以下内容:

 Customers //properties: ID, Name, Address
 IEnumberable<CustomerSports> //properties: CustomerID, SportsID
 IEnumberable<CustomerLocation> //properties: CustomerID, LocationID
 IEnumberable<CustomerPets> //properties: CustomerID, PetsID

所以我可以进行如下查询:

向我提供一份客户名单,其中包括长曲棍球,足球,足球(CustomerSports)...以及生活在纽约(CustomerLocation)的狗和猫(CustomerPets)。查询表可以为空,因此客户可以进行体育运动,但没有宠物。

然后当我得到客户列表时,我将加入客户表上的公共列(CustomerID)以检索ID,名称和地址。

我正在考虑让客户表加入每个查找,然后进行联合以获取客户列表,但我不知道这是否是正确的方法。

2 个答案:

答案 0 :(得分:4)

只要您正确设置了设计,那么每个Customer应该有一个Sports集合,一个Pets集合和一个Locations(除非最后一个是{一对一加入?)。

如果设置了这些关系,那么您可以按如下方式进行查询:

var sports = new string[] { "lacrosse", "football", "soccer" };
var pets = new string[] { "cat", "dog" };
var locations = new string[] { "new york" };
var sportyPetLoversInNewYors = db.Customers
    .Where(cust => sports.All(sport => cust.Sports.Any(custSport => custSport.Name == sport)))
    .Where(cust => pets.All(pet => cust.Pets.Any(custPet => custPet.Name == pet)))
    .Where(cust => locations.All(loc => cust.Locations.Any(custLoc => custLoc.Name = loc)))
    // could customise the select here to include sub-lists or whatever
    .Select();

这假设您只希望拥有所有6个条件的人。如果你想要至少喜欢其中一项运动的人,至少有一只宠物,并且(假设你使用了多个位置)至少在其中一个位置,那么Where表达式就会改变以下

.Where(cust => cust.Sports.Any(custSport => sports.Contains(custSport.Name)))

如果您需要进一步解释,请与我们联系。

答案 1 :(得分:1)

这样做的一种方法,如果我明白你所追求的是什么。允许多种运动和多只宠物,或者不允许。

        var contacts = from cust in customer
                       join sport in sports on cust.CustomerID equals sport.CustomerID into multisport from sport in multisport.DefaultIfEmpty()
                       join loc in location on cust.CustomerID equals loc.CustomerID
                       join pet in pets on cust.CustomerID equals pet.CustomerID into multipet from pet in multipet.DefaultIfEmpty()

                       select new
                       {
                           cust.CustomerID,
                           multisport,
                           loc.LocationID,
                           multipet
                       };