以多对多关系获取数据

时间:2013-11-21 17:21:28

标签: c# asp.net-mvc linq entity-framework

我有三个实体:

public class KeywordSearch
{
    // Primary properties
    public int Id { get; set; }
    public string Name { get; set; }

    // Navigation properties
    public Keyword Keyword { get; set; }
}

public class Keyword
{
    // Primary properties
    public int Id { get; set; }
    public string Name { get; set; }

    // Navigation properties
    public virtual ICollection<Address> Addresses { get; set; }
}

public class Address
{
    // Primary properties
    public int Id { get; set; }
    public PTCouncil PTCouncil { get; set; }                 <---------- EDIT

    // Navigation properties
    public virtual ICollection<Keyword> Keywords { get; set; }
}

public class PTCouncil                                       <---------- EDIT
{
    // Primary properties
    public int Id { get; set; }
    public string Name { get; set; }
}

基于一组单词,我需要提取所有不同的地址ID。

在KeywordSearch表中搜索的单词与关键字匹配,与地址相关。

到目前为止,在William的帮助下,我有了这个,但是获得了匹配所有和一些要搜索的单词的关键字,我需要得到所有这些:

编辑:

var addressIds = (
              from ks in keywordSearchQuery
              where splitKeywords.Contains(ks.Name)
              select ks.Keyword.Addresses.Select(k => k.Id)
             )
             .ToList()
             .Aggregate((a, b) => a.Intersect(b));

示例:

KeywordSearch = {1,"RENAULT",1},{2,"MORAIS",2},{3,"SOARES",3},{4,"CENTRO",4}
Keyword       = {1,"Renault",{1,2}},{2,"Morais",{1}},{3,"Soares",{1}},{4,"Centro",{2}}
Address       = {1,"Renault Morais Soares",{1,2,3}},{2,"Renault Centro",{1,2}}

If I search "RENAULT MORAIS SOARES", I should get AddressId = 1
If I search "RENAULT CENTRO", I should get AddressId = 2
If I search "RENAULT", I should get AddressId = 1,2

Actual Search Problem: If I search "RENAULT XXXX", I get 1,2 and I should get nothing.

我还需要按位置进行过滤,我试过这个但是我收到错误“LINQ to Entities不支持指定的类型成员'PTCouncil'

keywordsAddressIds = from ks in keywordSearchQuery
                     where splitKeywords.Contains(ks.Name)
                     select ks.Keyword.Addresses.Where(p => p.Location.Distance(centerPoint) < radius * 1000).Select(a => a.Id);

有什么想法吗?

感谢。

4 个答案:

答案 0 :(得分:3)

您需要在我认为的两个操作中执行此操作。

首先获取所有关键字地址:

var result = from ks in keywordSearchQuery
           where splitKeywords.Contains(ks.Name)
           select ks).ToList().Aggregate((a, b) => a.Intersect(b));

然后查看是否所有关键字都有结果,如果没有,则不返回任何内容

if (splitKeywords.Any(s => !result.Any(t => t.Name.Contains(s))))
            {
                return null;
            }

这是伪代码,但我认为你应该能够从这里弄明白。


- EDIT-- 出于好奇,你不是已经使用过多个操作吗?除非所有标准都已满,否则是否要阻止数据库调用? 但是当你执行.ToList()时,用DB中的数据(操作1)填充列表,然后填充到Aggregate + Intersect(操作2?)。我假设您可以以相同的方式添加第二个操作(代码未测试) - &gt;

var result = from ks in keywordSearchQuery
               where splitKeywords.Contains(ks.Name)
               select ks).ToList().Aggregate((a, b) => a.Intersect(b)).Any(s => !result.Any(t => t.Name.Contains(s)));

答案 1 :(得分:2)

看起来现在有几个问题,我将重点关注问题的关键字部分:

如果splitKeywords只需要与地址“关键字(原始答案)”进行交互

var addressIds = (
                  from ks in keywordSearchQuery
                  where splitKeywords.Contains(ks.Name)
                  select ks.Keyword.Addresses.Select(k => k.Id)
                 )
                 .ToList()
                 .Aggregate((a, b) => a.Intersect(b));

如果splitKeywords必须是地址'keywords

的SUBSET

请注意我是如何直接引用您的上下文addresses而不再通过您的keywordSearchQuery。这种方式更简单。

var addressIds = (
                  from a in addresses
                  where !splitKeywords.Except(a.Keywords.Select(kw => kw.Name)).Any()
                  select a.Id
                 )
                 .ToList();

我通过链接到硬编码对象来测试这两个。 LINQ to Entities中可能无法使用新的 子集 查询。让我知道!

答案 2 :(得分:0)

好的,你需要使用Aggregate和Intersect:

 var result = (from ks in keywordSearchQuery
               where splitKeywords.Contains(ks.Name)
               select ks.Keyword.Addresses.Select(a => a.Id))
              .Aggregate((l1, l2) => l1.Intersect(l2))

答案 3 :(得分:0)

我认为你应该尝试使用内连接,也用于从许多表中获取数据

从TABLE1上选择TABLE1.Field1,TABLE1.Field2,TABLE2.Field1在TABLE1.Field1上的INNER JOIN TABLE2 = TABLE2.Field1