LINQ-to-SQL GroupBy через разделение «многие ко многим» - PullRequest
1 голос
/ 04 ноября 2010

У меня есть следующая проблема для решения.

У меня есть список счетов IQueryable, каждый из которых привязан к учетной записи.Каждая учетная запись может иметь несколько структур, а учетные записи и структуры связаны между собой таблицей с именем StructureAccount.Выглядит это так:

Счет-фактура ---> Счет <----- StructureAccount ----> Структура

Я хочу запросить мой список счетов-фактур IQueryable и сгруппировать их по структуре.StructureID или StructureAccount.StructureID.Но, поскольку любой данный счет-фактура может быть привязан к нескольким структурам, лучшее, что я могу получить, это СПИСОК StructureID, и поэтому мой GroupBy не работает.

Мне кажется, что я упускаю очевидное решение для этого.

Следует отметить, что я понимаю, что данные в любом одном счете-фактуре будут подсчитываться несколько раз, если счет-фактура привязана к более чем одной структуре, и это "решается" значением "PercentAllocationtoStructure" в таблице StructureAccount.

Я надеюсь, что достаточно хорошо объяснил эту проблему.Дайте мне знать, если нет.

Ответы [ 2 ]

1 голос
/ 08 ноября 2010

Я предполагаю, что у вас есть следующая отправная точка:

IQueryable<Invoice> _invoices;

Во-первых, вам нужно получить список всех элементов, над которыми вы будете перебирать:

IQueryable<Account> _accounts = _invoices.Select(myInvoice => myInvoice.Account).Distinct();
IQueryable<StructuredAccount> _structuredAccounts = _accounts.SelectMany(myAccount => myAccount.StructuredAccounts);
IQueryable<Structure> _structures = _structuredAccounts.Select(myStructuredAccount => myStructuredAccount.Structure).Distinct();

Затем вам нужно вернуться и присоединить ваши Structure объекты к соответствующим Invoice объектам.

Для этого вы:

  1. Получить набор из {Structure, Account} пар:

    var structureAccountJoin = _structures.Join (_structuredAccounts, _structure => Structure.StructuredID, _structuredAccount => _structuredAccount.StructuredID, (структура, structdAccount) => new {Structure = структура, Account = structdAccount.Account});

  2. Получить набор из {Structure, Invoice} пар:

    var structureInvoiceJoin = structureAccountJoin.Join (_invoices, myObj => myObj.Account.AccountID, invoice => invoice.AccountID, (myObj, invoice) => new {Structure = myObj.Structure, Invoice = invoice); счет-фактура 1025 *

Наконец, вы можете сгруппировать все по объекту Structure:

IQueryable<IGrouping<Structure, Invoice>> groupByStructure = structureInvoiceJoin.GroupBy(obj => obj.Structure, result => result.Invoice);

(документация GroupBy: http://msdn.microsoft.com/en-us/library/bb534304.aspx)

Теперь вы можете получить доступ ко всему следующим образом:

foreach(IGrouping<Structure, Invoice> groupEntry in groupByStructure)
{
     Structure currentGrouping = groupEntry.Key;

     foreach(Invoice inv in groupEntry)
     {
           // do something;
     }
}

Как примечание, это очень сложный сценарий, который требует много шагов, если у вас нет прямого доступа к таблицам. Возможно, вы захотите создать для этого StoredProcedure, так как он будет более эффективным, и вы сможете вместо этого использовать SQL-соединения. Если у вас есть только IQueryable<Invoice> для работы и доступа к чему-либо еще, возможно, в вашей архитектуре есть проблема дизайна.

Тем не менее, это способ заставить его работать на основе ваших требований, если я правильно их прочитал.

1 голос
/ 05 ноября 2010

Хммм ... Может я что-то упустил, но разве не работает?

var q = from i in Invoice
        join a in Account
        on i.AccountID equals a.AccountID
        join sa in StructureAccount
        on i.AccountID equals sa.AccountID
        join s in Structure
        on sa.StructureID equals s.StructureID
        group i by s.StructureID;

Я проверил это на следующих фиктивных данных:

var Invoice = new [] {
    new { InvoiceID = 1, AccountID = 1 },
    new { InvoiceID = 2, AccountID = 2 },
    new { InvoiceID = 3, AccountID = 3 },
    new { InvoiceID = 4, AccountID = 1 },
    new { InvoiceID = 5, AccountID = 2 },
    new { InvoiceID = 6, AccountID = 3 }
};

var Account = new [] {
    new { AccountID = 1 },
    new { AccountID = 2 },
    new { AccountID = 3 },
};

var StructureAccount = new [] {
    new { AccountID = 1, StructureID = 2 },
    new { AccountID = 1, StructureID = 3 },
    new { AccountID = 2, StructureID = 2 },
    new { AccountID = 3, StructureID = 1 },
    new { AccountID = 3, StructureID = 2 },
};

var Structure = new [] {
    new { StructureID = 1 },
    new { StructureID = 2 },
    new { StructureID = 3 }
};

И он возвращает:

StructureID = 2:
    InvoiceID's: 1,2,3,4,5,6

StructureID = 3:
    InvoiceID's: 1,4

StructureID = 1:
    InvoiceID's: 3,6
...