LINQ 增添神秘感“1”到生成的 SQL 中我的 int

发布于 2024-12-04 22:54:10 字数 1868 浏览 1 评论 0原文

我不得不承认,我只是计划被难住了......我有下面的 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)

然而,当我通过 context.Log = Console.Out 检查时,正在生成的 SQL 是这样的 -->

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之外,它实际上相当接近!

WTH?!?

我什至通过删除生成的 SQL 中的 +1 并运行它来验证它是否正确,生成与原始 SQL 相同的结果。

那么,我错过了什么或做错了什么?这是众所周知的 LINQ 的做法吗?LOL 是为了对付我们这些才华横溢的程序员吗?

I have to admit, I am just plan stumped....I have the below LINQ to SQL Method -->

    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)))
                            );
        }
    }

This was made based from a SQL query written by a co-worker to achieve nearly the same thing -->

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)

However, the SQL that is being generated, when I check through context.Log = Console.Out is this-->

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]

You can see that it is actually fairly close with the GLARING exception of some added +1's!!!

WTH?!?

I even verified that it WOULD be correct by removing the +1's in the generated SQL and running it with it generating the same results as the original SQL.

So, what am I missing or doing wrong? Is this a well know LOL of LINQ's to screw with us less talented programmers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

平定天下 2024-12-11 22:54:10

SQL Server 的 SUBSTRING 使用从 1 开始的索引,而 string.Substring 使用从 0 开始的索引。 + 1 在基数之间进行映射以保留 C# 语义。

至于为什么必须删除 + 1 才能使其正常工作,这对我来说是个谜。

SQL Server's SUBSTRING uses 1-based indexing, whereas string.Substring uses zero-based indexing. The + 1 maps between the bases to preserve the C# semantics.

As to why you had to remove the + 1 to make it work correctly, that's a mystery to me.

睡美人的小仙女 2024-12-11 22:54:10

@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 名员工,但这可能会在以后影响到您。

我建议您分解上述方法并给它们指定适当的名称,以增强可读性。例如getEmployeeNumber(stringinvoiceNumber)等。

@MarceloCantos answer is correct, but here is the explanation as to why it works when you remove the + 1:

You have converted
SUBSTRING([InvoiceNumber], 3, 4) to gs.InvoiceNumber.Substring(3, 4) but since C# uses zero-based index you should actually use gs.InvoiceNumber.Substring(2, 4) to start at the third character.

Similarly you should use gs.InvoiceNumber.Substring(6) as the substitution for SUBSTRING([InvoiceNumber], 7, LEN([InvoiceNumber])). Note that there is no need to specify the length of the substring in C# if you want all that is after the index. Actually gs.InvoiceNumber.Substring(7, gs.InvoiceNumber.Length) would cause an ArgumentOutOfRangeException if you tried to use it separately, but now that it is translated to T-SQL it actually works.

On a side note SUBSTRING([InvoiceNumber], 1, 6) AS EmpNumber seems to indicate that it the first six characters are the EmployeeNumber but you are only looking at the last four of them. Presumably because you only have < 10000 Employees at the moment, but this might come back to bite you later.

I would suggest you break out the methods above and give them proper names, to enhance readability. E.g. getEmployeeNumber(string invoiceNumber), etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文