2012-03-15 2 views
62

Я пытаюсь выполнить команду . Соединитесь между несколькими таблицами в LINQ. У меня есть следующие классы:Как выполнить соединение между несколькими таблицами в LINQ lambda

Product {Id, ProdName, ProdQty} 

Category {Id, CatName} 

ProductCategory{ProdId, CatId} //association table 

И я использую следующий код (где product, category и productcategory являются экземпляры вышеуказанных классов):

var query = product.Join(productcategory, p => p.Id, pc => pc.ProdID, (p, pc) => new {product = p, productcategory = pc}) 
        .Join(category, ppc => ppc.productcategory.CatId, c => c.Id, (ppc, c) => new { productproductcategory = ppc, category = c}); 

С помощью этого кода я получаю объект от следующий класс:

QueryClass { productproductcategory, category} 

Где producproductcategory имеет тип:

ProductProductCategoryClass {product, productcategory} 

Я не понимаю, где присоединился к «стол», я ожидал один класс, который содержит все свойства из участвующих классов.

Моя цель состоит в том, чтобы заполнить другой объект, с некоторыми свойствами в результате запроса:

CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments }); 

как я могу достичь этой цели?

+0

Я не понял ... почему ** m.ProdId = ??? ** вместо ** prodId = m.ProdId **? –

+0

Потому что я не знаю заранее, как перемещаться и получать ProdId – CiccioMiami

ответ

124

Для объединения, я настоятельно предпочитаю запрос-синтаксис для всех деталей, которые, к счастью, скрытых (не в последнюю очередь из которых являются прозрачными идентификаторы, связанные с промежуточными проекциями на пути, которые очевидны в эквиваленте точки-синтаксиса). Однако вы спросили насчет Лямбдаса, который, я думаю, у вас есть все, что вам нужно - вам просто нужно собрать все это вместе.

var categorizedProducts = product 
    .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc }) 
    .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { ppc, c }) 
    .Select(m => new { 
     ProdId = m.ppc.p.Id, // or m.ppc.pc.ProdId 
     CatId = m.c.CatId 
     // other assignments 
    }); 

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

Кроме того, вы можете бросить Select в последнюю лямбду второго Join (опять же, при условии, нет никаких других операций, которые зависят от результатов присоединиться), который дал бы:

var categorizedProducts = product 
    .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc }) 
    .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { 
     ProdId = ppc.p.Id, // or ppc.pc.ProdId 
     CatId = c.CatId 
     // other assignments 
    }); 

... и что делает последнюю попытку продать вам на синтаксис запроса, это будет выглядеть так:

var categorizedProducts = 
    from p in product 
    join pc in productcategory on p.Id equals pc.ProdId 
    join c in category on pc.CatId equals c.Id 
    select new { 
     ProdId = p.Id, // or pc.ProdId 
     CatId = c.CatId 
     // other assignments 
    }; 

Ваши руки могут быть связаны ли доступен запрос-синтаксис. Я знаю, что некоторые магазины имеют такие мандаты - часто на основе понятия, что синтаксис запроса несколько более ограничен, чем точечный синтаксис. Существуют и другие причины, такие как «почему я должен изучить второй синтаксис, если я могу делать все и многое другое в точечном синтаксисе?«Как показывает эта последняя часть - есть детали, которые скрывают синтаксис запросов, которые могут сделать его достойным охвата, с улучшением читаемости, которое он приносит: все те промежуточные проекции и идентификаторы, которые вы должны готовить, счастливы не передними и центральными -ступень в версии запросов синтаксиса - они являются фоновым пухом Off моего мыла ящик сейчас -.. в любом случае, спасибо за вопрос :)

+3

Спасибо, что ваше решение более полно. Я согласен, синтаксис запроса в некоторых случаях более ясен, но вы догадались, меня попросили использовать лямбда. Кроме того, я должен сделать это объединяет более 6 таблиц, а точечное обозначение в этом случае более аккуратное – CiccioMiami

+0

+1 Perfect ... !!! –

+0

@devgeezer Что делать, если нам нужно условие добавления в инструкции 'JOIN'? Как мы это делаем? Например, в 'join pc в productcategory на p.Id равна pc.ProdId' строка, нам нужно добавить' и p.Id == 1'. –

9

То, что вы видели, что вы получите, - и это именно то, что вы просили, здесь:

(ppc, c) => new { productproductcategory = ppc, category = c} 

Это лямбда-выражение возвращающий анонимный тип с этими двумя свойствами.

В ваших CategorizedProducts, вам просто нужно идти через эти свойства:

CategorizedProducts catProducts = query.Select(
     m => new { 
      ProdId = m.productproductcategory.product.Id, 
      CatId = m.category.CatId, 
      // other assignments 
      }); 
+0

Спасибо. Я понимаю обсуждение анонимного класса, но его свойства содержат только объекты класса, которые выполняют запрос? И что произойдет после того, как я исполнил 2-го? productproductcategory.product не присоединился к категории правильно? – CiccioMiami

+0

@CiccioMiami: Ну, свойства - это * ссылки * на объекты, да. Не совсем понятно, что вы подразумеваете под «не присоединились» - какую информацию вы не получаете из своего запроса, который хотите получить? –

+0

С первым соединением я получаю соединение между продуктами и товарной категорией. Со вторым я получаю соединение между товарной категорией (объединенным продуктом) и категорией. Это означает, что информация о множественном соединении содержится только в товарной продукции. Это означает, что продукт (и категория) только что соединен с товарной категорией. – CiccioMiami

3

принимает взгляд на этом образце коде из моего проекта

public static IList<Letter> GetDepartmentLettersLinq(int departmentId) 
{ 
    IEnumerable<Letter> allDepartmentLetters = 
     from allLetter in LetterService.GetAllLetters() 
     join allUser in UserService.GetAllUsers() on allLetter.EmployeeID equals allUser.ID into usersGroup 
     from user in usersGroup.DefaultIfEmpty()// here is the tricky part 
     join allDepartment in DepartmentService.GetAllDepartments() on user.DepartmentID equals allDepartment.ID 
     where allDepartment.ID == departmentId 
     select allLetter; 

    return allDepartmentLetters.ToArray(); 
} 

в этом коде я присоединился к 3 таблицам, и я включил условие соединения, из которого:

примечание: классы Services просто деформированы (encapsu поздно) операции с базой данных

1
public ActionResult Index() 
    { 
     List<CustomerOrder_Result> obj = new List<CustomerOrder_Result>(); 

     var orderlist = (from a in db.OrderMasters 
         join b in db.Customers on a.CustomerId equals b.Id 
         join c in db.CustomerAddresses on b.Id equals c.CustomerId 
         where a.Status == "Pending" 
         select new 
         { 
          Customername = b.Customername, 
          Phone = b.Phone, 
          OrderId = a.OrderId, 
          OrderDate = a.OrderDate, 
          NoOfItems = a.NoOfItems, 
          Order_amt = a.Order_amt, 
          dis_amt = a.Dis_amt, 
          net_amt = a.Net_amt, 
          status=a.Status, 
          address = c.address, 
          City = c.City, 
          State = c.State, 
          Pin = c.Pin 

         }) ; 
     foreach (var item in orderlist) 
     { 

      CustomerOrder_Result clr = new CustomerOrder_Result(); 
      clr.Customername=item.Customername; 
      clr.Phone = item.Phone; 
      clr.OrderId = item.OrderId; 
      clr.OrderDate = item.OrderDate; 
      clr.NoOfItems = item.NoOfItems; 
      clr.Order_amt = item.Order_amt; 
      clr.net_amt = item.net_amt; 
      clr.address = item.address; 
      clr.City = item.City; 
      clr.State = item.State; 
      clr.Pin = item.Pin; 
      clr.status = item.status; 

      obj.Add(clr); 



     } 
+1

Хотя этот фрагмент кода может решить вопрос, [включая объяснение] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) действительно помогает улучшить качество вашего сообщения.Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. –

Смежные вопросы