LINQ добавляет загадку «+1» к моим int в сгенерированном SQL - PullRequest
0 голосов
/ 17 сентября 2011

Я должен признать, я просто поставил в тупик .... У меня есть метод LINQ to SQL ниже ->

    public static int GetLastInvoiceNumber(int empNumber)
    {
        using (var context = CmoDataContext.Create())
        {
            context.Log = Console.Out;

            IQueryable<tblGreenSheet> tGreenSheet = context.GetTable<tblGreenSheet>();
            return (tGreenSheet
                            .Where(gs => gs.InvoiceNumber.Substring(3, 4) == empNumber.ToString())
                            .Max(gs => Convert.ToInt32(gs.InvoiceNumber.Substring(7, gs.InvoiceNumber.Length)))
                            );
        }
    }

Это было сделано на основе запроса SQL, написанного соавторомрабочий для достижения почти того же самого ->

SELECT DISTINCT 
SUBSTRING([InvoiceNumber], 1, 6) AS EmpNumber,
MAX(CAST(SUBSTRING([InvoiceNumber], 7, LEN([InvoiceNumber])) AS INT)) AS MaxInc
FROM [CMO].[dbo].[tblGreenSheet]
WHERE SUBSTRING([InvoiceNumber], 3, 4) = '1119' --EmployeeNumber
GROUP BY SUBSTRING([InvoiceNumber], 1, 6)

Тем не менее, SQL, который генерируется, когда я проверяю через context.Log = Console.Out, это ->

SELECT MAX([t1].[value]) AS [value]
FROM (
    SELECT CONVERT(Int,SUBSTRING([t0].[InvoiceNumber], @p0 + 1, LEN([t0].[InvoiceNumber]))) AS [value], [t0].[InvoiceNumber]
    FROM [dbo].[tblGreenSheet] AS [t0]
    ) AS [t1]
WHERE SUBSTRING([t1].[InvoiceNumber], @p1 + 1, @p2) = @p3
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [7]
-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [3]
-- @p2: Input Int (Size = 0; Prec = 0; Scale = 0) [4]
-- @p3: Input VarChar (Size = 4; Prec = 0; Scale = 0) [1119]

Вы можете видеть, что это на самом деле довольно близко, за исключением GLARING некоторых добавленных +1 's !!!

WTH?!?

Я даже проверил, что он будет верен, удалив +1 в сгенерированном SQL и запустив его с его генерацией.результаты как исходный SQL.

Итак, что я пропускаю или делаю неправильно?Это хорошо известно LOL о LINQ, чтобы связать нас с менее талантливыми программистами?

Ответы [ 2 ]

5 голосов
/ 17 сентября 2011

SUBSTRING SQL Server использует индексацию на основе 1, тогда как string.Substring использует индексацию на основе нуля. + 1 сопоставляет базы, чтобы сохранить семантику C #.

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

2 голосов
/ 03 ноября 2011

@ MarceloCantos ответ правильный, но вот объяснение, почему оно работает при удалении + 1:

Вы преобразовали SUBSTRING([InvoiceNumber], 3, 4) до gs.InvoiceNumber.Substring(3, 4), но так как C # использует индекс, начинающийся с нуля, вы должны использовать gs.InvoiceNumber.Substring(2, 4), чтобы начать с третьего символа.

Аналогично, вы должны использовать gs.InvoiceNumber.Substring(6) в качестве замены для SUBSTRING([InvoiceNumber], 7, LEN([InvoiceNumber])). Обратите внимание, что нет необходимости указывать длину подстроки в C #, если вы хотите все, что находится после индекса. На самом деле gs.InvoiceNumber.Substring(7, gs.InvoiceNumber.Length) вызовет ArgumentOutOfRangeException, если вы попытаетесь использовать его отдельно, но теперь, когда он переведен в T-SQL, он действительно работает.

На боковой ноте SUBSTRING([InvoiceNumber], 1, 6) AS EmpNumber, кажется, указывается, что первые шесть символов EmployeeNumber, но вы смотрите только на последние четыре из них. Предположительно, потому что у вас есть только <10000 сотрудников в данный момент, но это может вернуться к вам позже. </p>

Я бы посоветовал вам вычеркнуть описанные выше методы и дать им собственные имена, чтобы улучшить читаемость. Например. getEmployeeNumber(string invoiceNumber) и т. Д.

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