2014-02-17 123 views
1

这一直困扰着我一段时间,因为我试图想出一个优化的查询方式。多个交叉参考表加入linq

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

例如:

比方说,我有以下几点:

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

这样我就可以进行查询,如:

给我玩曲棍球,橄榄球,足球的客户名单(CustomerSports)......并且有住在纽约(客户位置)的狗和猫(CustomerPets)。查找表可以为空,所以客户可以玩运动,但没有宠物。

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

我在考虑在每次查询时让客户表加入,然后通过联合来获取客户列表,但我不知道这是否是正确的方式。

+1

您希望拥有宠物或玩运动的客户(左外连接),还是只有拥有所有这些功能的客户? (你在问题中使用了AND两个字,但是你提到一些客户可以做一个而不是另一个让我认为你的意思是OR)。 –

+0

在这里浏览它可能会导致一些见解。 http://msdn.microsoft.com/en-us/library/bb399397%28v=vs.110%29.aspx – Andy

回答

3

只要你有设置你的设计正确,则每个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))) 

让我知道你是否需要进一步的解释。

+0

我意识到这是我真正的解决方案。我对过滤器有更多的控制权,而不是进行连接。当我尝试连接时,它会为所有表做内部处理。但事情是,我需要它根据3个数据源进行过滤,如果有任何运动项目,任何宠物或任何位置。如果我做了连接,并且其中任何一个都是空的,它将返回一个空集。 – sksallaj

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 
         };