Сравнение Linq и SQL запросов - PullRequest
0 голосов
/ 04 апреля 2011

У меня есть этот запрос SQL:

SELECT Sum(ABS([Minimum Installment])) AS SumOfMonthlyPayments FROM tblAccount 
INNER JOIN tblAccountOwner ON tblAccount.[Creditor Registry ID] = tblAccountOwner.
[Creditor Registry ID] AND tblAccount.[Account No] = tblAccountOwner.[Account No] 
WHERE (tblAccountOwner.[Account Owner Registry ID] = 731752693037116688)
 AND (tblAccount.[Account Type] NOT IN 
('CA00', 'CA01', 'CA03', 'CA04', 'CA02', 'PA00', 'PA01', 'PA02', 'PA03', 'PA04'))
AND (DATEDIFF(mm, tblAccount.[State Change Date], GETDATE()) <= 
4 OR tblAccount.[State Change Date] IS NULL)
AND ((tblAccount.[Account Type] IN ('CL10','CL11','PL10','PL11')) OR
CONTAINS(tblAccount.[Account Type], 'Mortgage')) AND (tblAccount.[Account Status ID] <> 999)   

Я создал запрос Linq:

var ownerRegistryId = 731752693037116688;
var excludeTypes = new[]
{
    "CA00", "CA01", "CA03", "CA04", "CA02",
    "PA00", "PA01", "PA02", "PA03", "PA04"
};

var maxStateChangeMonth = 4;
var excludeStatusId = 999;
var includeMortgage = new[] { "CL10", "CL11", "PL10", "PL11" };

var sum = (
    from account in context.Accounts
    from owner in account.AccountOwners
    where owner.AccountOwnerRegistryId == ownerRegistryId
    where !excludeTypes.Contains(account.AccountType)
    where account.StateChangeDate == null ||
       (account.StateChangeDate.Month - DateTime.Now.Month)
            <= maxStateChangeMonth
    where includeMortgage.Contains(account.AccountType) ||
        account.AccountType.Contains("Mortgage")
    where account.AccountStatusId != excludeStatusId
    select account.MinimumInstallment).ToList()
    .Sum(minimumInstallment =>
        Math.Abs((decimal)(minimumInstallment)));

return sum;

Они равны / одинаковы? У меня нет записей в БД, поэтому я не могу подтвердить, равны ли они. В SQL есть скобки (), но в Linq я их не использовал, так что все в порядке?

Пожалуйста, предложите.

Ответы [ 3 ]

1 голос
/ 04 апреля 2011

Скобки будут сгенерированы провайдером LINQ, если необходимо.
Самый простой способ проверить, равен ли запрос LINQ исходному запросу SQL, - зарегистрировать его, как предложил @Atanas Korchev.
Однако если вы используете Entity Framework, свойства Log нет, но вы можете попытаться преобразовать свой запрос в ObjectQuery и вызвать метод ToTraceString:
string sqlQuery = (sum as ObjectQuery).ToTraceString();
UPD . Метод ToTraceString нуждается в экземпляре ObjectQuery для трассировки, а вызов ToList () уже выполняет материализацию, поэтому отследить нечего. Вот обновленный код:

var sum = (
from account in context.Accounts
from owner in account.AccountOwners
where owner.AccountOwnerRegistryId == ownerRegistryId
where !excludeTypes.Contains(account.AccountType)
where account.StateChangeDate == null ||
   (account.StateChangeDate.Month - DateTime.Now.Month)
        <= maxStateChangeMonth
where includeMortgage.Contains(account.AccountType) ||
    account.AccountType.Contains("Mortgage")
where account.AccountStatusId != excludeStatusId
select account.MinimumInstallment);
string sqlQuery = (sum as ObjectQuery).ToTraceString();  

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

1 голос
/ 04 апреля 2011

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

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

  1. Вставьте данные в базу данных и выполните запросы.
  2. Используйте профилировщик SQL и посмотрите, какой запрос выполняется вашим поставщиком LINQ под прикрытием.

Если у вас есть что-то более конкретное, мы будем очень рады помочь.

0 голосов
/ 04 апреля 2011

Может быть разница в производительности:

Запрос SQL возвращает одно число (SELECT Sum...) непосредственно с сервера базы данных клиенту, который выполняет запрос.

В вашем LINQзапрос у вас есть жадный оператор (.ToList()) между:

var sum = (...
    ...
    select account.MinimumInstallment).ToList()
    .Sum(minimumInstallment =>
        Math.Abs((decimal)(minimumInstallment)));

Это означает, что запрос на сервере SQL не содержит операцию .Sum.Запрос возвращает (потенциально длинный?) Список MinimumInstallments.Затем операция .Sum выполняется в памяти на клиенте.

Таким образом, вы эффективно переключаетесь с LINQ на Entities на LINQ to Objects после .ToList().

Кстати: вы можете проверить последнее предложение в вашем предыдущем вопросе здесь избегайте .ToList() в этом запросе (если предложение должно работать) и, следовательно, будет ближе к оператору SQL.

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