如何使用LINQ-to-SQL连接多个表?

时间:2011-02-04 14:43:13

标签: join linq-to-sql

我对linq很新,所以请耐心等待。

我正在开发一个asp.net网页,我想添加一个“搜索功能”(文本框,用户输入名称或姓氏或两者或只是其中的一部分,并获取所有相关信息)。我有两个表(“人”和“应用程序”),我想显示一些来自Person(姓名和姓氏)的列和一些来自Application(得分,位置......)的列。我知道如何使用sql做到这一点,但我想了解更多关于linq的信息,因此我想用linq来做。

现在我有两个主要想法:

1)

    var person = dataContext.GetTable<Person>();
    var application = dataContext.GetTable<Application>();
    var p1 = from p in Person
             where(p.Name.Contains(tokens[0]) || p.Surname.Contains(tokens[1]))
             select new {Id = p.Id, Name = p.Name, Surname = p.Surname}; //or maybe without this line

 //I don't know how to do the following properly
 var result = from a in Application
                 where a.FK_Application.Equals(index)  //just to get the "right" type of application
                 //this is not right, but I don't know how to do it better
                 join p1
                 on p1.Id == a.FK_Person

2。)另一个想法只是通过“应用程序”而不是“加入p1 ......”来使用

var result = from a in Application
             where a.FK_Application.Equals(index)  //just to get the "right" type of application
             join p from Person
             on p.Id == a.FK_Person
             where p.Name.Contains(tokens[0]) || p.Surname.Contains(tokens[1])      

我认为对于没有第一个“where”条件的查询,第一个想法更好,我也打算使用它。无论什么更好(更快),我仍然不知道如何使用linq。最后,我想显示/选择结果的某些部分(列)(连接表+过滤条件)。

我真的想知道如何使用linq做这些事情,因为我将处理本地数据的一些类似问题,我只能使用linq。 有人可以解释一下如何做到这一点,我花了几天时间试图弄清楚并在互联网上搜索答案。

2 个答案:

答案 0 :(得分:3)

var result = from a in dataContext.Applications
             join p in dataContext.Persons
             on p.Id equals a.FK_Person
             where (p.Name.Contains("blah") || p.Surname.Contains("foo")) && a.FK_Application == index
             select new { Id = p.Id, Name = p.Name, Surname = p.Surname, a.Score, a.Position };

正如Odrahn所指出的那样,这会给你一个平坦的结果,可能有很多行供一个人使用,因为一个人可以加入多个具有相同FK的应用程序。这是一种搜索所有合适人员的方法,然后将相关应用程序添加到结果中:

var p1 = from p in dataContext.Persons
             where(p.Name.Contains(tokens[0]) || p.Surname.Contains(tokens[1]))
             select new {
                Id = p.Id, Name = p.Name, Surname = p.Surname,
                BestApplication = dataContext.Applications.FirstOrDefault(a => a.FK_Application == index /* && ????  */); 
         }; 

抱歉 - 看起来这第二个查询会导致每人往返,所以它显然不具备可扩展性。我认为L2S会更好地处理它。

答案 1 :(得分:1)

为了正确回答这个问题,我需要知道Application和Person是否直接相关(即Person有多个应用程序)?从阅读你的帖子,我假设他们是因为应用程序似乎有人的外键。

如果是这样,那么您可以创建一个自定义PersonModel,它将由您需要的字段填充,如下所示:

class PersonModel
{
    string Name { get; set; }
    string Surname { get; set; }
    List<int> Scores { get; set; }
    List<int> Positions { get; set; }
}

然后填充它,您将执行以下操作:

// Select the correct person based on Name and Surname inputs
var person = dataContext.Persons.Where(p => p.Name.Contains("firstname") || p.Name.Contains("surname")).FirstOrDefault(); 
// Get the first person we find (note, there may be many - do you need to account for this?)

if (person != null)
{
    var scores = new List<int>();
    var positions = new List<int>();

    scores.AddRange(person.Applications.Select(i => i.Score);
    positions.AddRange(person.Applications.Select(i => i.Position);

    var personModel = new PersonModel
                          {
                              Name = person.Name,
                              Surname = person.Surname,
                              Scores = scores,
                              Positions = positions
                          };
}

由于你和人和应用之间的关系,一个人可以有很多申请,我必须考虑到有很多分数和职位的可能性(因此列表)。

另请注意,我使用lambda表达式而不是简单的linqToSql进行简单选择,以便您可以轻松地查看正在发生的事情。