Как я могу оптимизировать этот запрос LINQ, чтобы выполнить только одну команду SQL? - PullRequest
1 голос
/ 22 июня 2010

Я использую Linq-To-Sql, чтобы заполнить свой бизнес-уровень.Вот фрагмент запроса, над которым я работаю:

fund.FundEntities = fundGroup.tFunds
    .Select(fe =>
    {
        var fundEntity = new FundEntity()
        {
            BankAccount = null,
            CloseDate = fe.closeDate ?? new DateTime(),
            Commitment = fe.commitment ?? 0,
            CommitmentEndDate = fe.closeDate ?? new DateTime(),
            Fund = fund
        };
        fundEntity.CapitalCalls = fe.tCapitalCalls
            .Select(cc =>
            {
                return new CapitalCall()
                {
                    Amount = cc.agrAmount ?? 0,
                    FundEntity = fundEntity
                };
            }
             );
        return fundEntity;
    });

Когда я запускаю этот код, он выполняет запросы для отдельных CapitalCalls во время выполнения.Можно ли как-нибудь изменить эту архитектуру, чтобы сохранить ту же структуру бизнес-объектов (т.е. отношения между Fund -> FundEntity -> CapitalCall внутри бизнес-объектов), но загружать полные таблицы за раз?В идеале это был бы один SQL-запрос с множеством объединений, что привело бы к заполнению фонда.

Ответы [ 4 ]

3 голосов
/ 22 июня 2010

Решением проблемы было бы одновременное выполнение нескольких запросов и связывание их результирующих данных.Хотя для LINQ to SQL это возможно, он изначально не поддерживает такие функции.

PLINQO - это альтернатива с открытым исходным кодом для замены и расширения альтернативы LINQ to SQL, которая добавляет дополнительные функциональные возможности в среду.В частности, вы будете заинтересованы в пакетных запросах и будущих запросах.

Проверьте это на http://www.plinqo.com

Надеюсь, что это поможет!-Tom DuPont (член команды разработчиков PLINQO)

1 голос
/ 22 июня 2010
var fund = GetFund();
var fundGroup = GetFundGroup();
var dataContest = GetDataContext();


List<int> feIds = fundGroup.tFunds.Select(fe => fe.FundEntityId).ToList();

 //before: iterate through local collection fundGroup.tFunds
 //  and issue one CapitalCall query per fundEntity.
 //after: send all the fundEntityIds into the database in one query
 //  that also fetches related CapitalCalls.
var query =
  from fe in dataContext.tFunds
  where feIds.Contains(fe.FundEntityId))
  let capitalCalls = fe.tCapitalCalls
  select new {FundEntity = fe, CapitalCalls = capitalCalls.ToList() };

foreach(var record in query)
{
  FundEntity fundEntity = new FundEntity()
  {
    CloseDate = record.fe.closeDate ?? new DateTime(),
    ...
  }
  fundEntity.CapitalCalls = ...
}
0 голосов
/ 23 июня 2010

Я бы пошел с чем-то вроде SteadyEddi (у меня есть FundEntity), но я думаю, что вы можете выразить это точно так, как вы хотите, как это (или эквивалентный способ не LINQ, как SteadyEddi):

fund.FundEntities =
from fe in fundGroup.tFunds
select new FundEntity()
{
    BackAccount = null,
    CloseDate = fe.closeDate ?? new DateTime(),
    Commitment = fe.commitment ?? 0,
    CommitmentEndDate = fe.closeDate ?? new DateTime(),
    Fund = fund,
    CapitalCalls = from cc in fe.tCapitalCalls
                   select new CapitalCall()
                   {
                       Amount = cc.agrAmount ?? 0,
                       FundEntity = fundEntity
                   }
}

Если нет, я думаю, что в вашем отображении базы данных происходит что-то, что действительно должно быть пересмотрено в любом случае :) Плохие имена и т.д. Проблема с вашим кодом может заключаться в том, что вы сами создаете CapitalCalls, поэтому LINQ-TO-SQL может быть не в состоянии правильно декодировать дерево выражений. Но опять же, я, очевидно, не тестировал свой код, поэтому я не знаю, работает ли мой код.

0 голосов
/ 23 июня 2010

Мне кажется, что вы идете назад, а не вперед.Вы пытаетесь перейти к Fund -> FundEntity -> CapitalCalls, но затем пытаетесь дать каждому ссылку на свой контейнер.

Вы можете сделать более простой запрос для базы данных, вызвав для нее ToList, а затемперепроектировать это в желаемую структуру, используя Linq to Objects.

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

Если вы думаете, что можете жить без ссылок на контейнеры, ваш запрос может быть выражен следующим образом:который должен использовать соединение в одном запросе.

fund.FundEntities = fundGroup.tFunds
.Select(fe =>
{
    new FundEntity
    {
        BankAccount = null,
        CloseDate = fe.closeDate ?? new DateTime(),
        Commitment = fe.commitment ?? 0,
        CommitmentEndDate = fe.closeDate ?? new DateTime(),
        CapitalCalls = fe.tCapitalCalls
        .Select(cc =>
        {
            new CapitalCall
            {
                Amount = cc.agrAmount ?? 0
            };
        }
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...