Как объединить несколько таблиц, используя LINQ-to-SQL? - PullRequest
2 голосов
/ 04 февраля 2011

Я совсем новичок в linq, поэтому, пожалуйста, потерпите меня.

Я работаю над веб-страницей asp.net и хочу добавить «функцию поиска» (текстовое поле, в котором пользователь вводит имя или фамилию или и то, и другое или только их часть и возвращает всю связанную информацию).У меня есть две таблицы («Персона» и «Приложение»), и я хочу отобразить некоторые столбцы из «Персона» (имя и фамилия) и некоторые из «Приложения» (оценка, должность, ...).Я знаю, как я могу сделать это с помощью 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])      

Я думаю, что первая идеялучше для запросов без первого условия "где", которое я также намеревался использовать.Независимо от того, что лучше (быстрее), я до сих пор не знаю, как это сделать с помощью linq.Также в конце я хотел отобразить / выбрать только некоторые части (столбцы) результата (объединенные таблицы + условия фильтрации).

Я действительно хочу знать, как делать такие вещи, используя linq, как я будутакже имеет дело с некоторыми похожими проблемами с локальными данными, где я могу использовать только linq.Может кто-нибудь объяснить мне, как это сделать, я потратил несколько дней, пытаясь выяснить это и искать в Интернете ответы.

Ответы [ 2 ]

3 голосов
/ 04 февраля 2011
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 };

Как отметил Одрахн, это даст вам точные результаты, возможно, с несколькими строками для одного человека, так как человек может присоединиться к нескольким приложениям, которые имеют одинаковый 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 голос
/ 04 февраля 2011

Чтобы ответить на этот вопрос должным образом, мне нужно знать, связаны ли Приложение и Лицо напрямую (т.е. много ли у Лица Приложений)?Читая ваш пост, я предполагаю, что это так, потому что у приложения, похоже, есть внешний ключ к человеку.

Если это так, то вы можете создать персонализированную 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
                          };
}

Из-за ваших отношений между Лицом и Приложением, когда у человека может быть много заявлений, мне пришлось учитывать возможность наличия множества баллов и позиций (отсюда и Список),

Также обратите внимание, что я использовал лямбда-выражения вместо простого linqToSql для простого выбора, чтобы вы могли легко визуализировать происходящее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...