【问题标题】:How can I return specific table columns with sp_executesql to LINQ2SQL or Entity Framework?如何使用 sp_executesql 将特定表列返回到 LINQ2SQL 或实体框架?
【发布时间】:2015-10-12 14:37:56
【问题描述】:

我有一个包含命令EXEC [sp_executesql] 的存储过程,并使用临时表#UserDetail 返回结果。

我在通过 LINQ2SQL 或实体框架返回数据时遇到问题。

我需要获取特定列并将这些列映射到我在 C# 中的业务对象。

当我在 Linq2SQL 中创建 DataContext 时出现错误:

The return types for the following stored procedures could not be detected

并且在实体框架存储过程中返回 int 不是特定的列。

如何修改这个存储过程来做到这一点?

CREATE PROC [SUPPORT].[GetUserDetail] @userId BIGINT
AS
    BEGIN

        CREATE TABLE #UserDetail
            (
              [UserId] BIGINT NOT NULL,
              [UserName] VARCHAR(50) NOT NULL,
              [Email] VARCHAR(150) NOT NULL
            )

        DECLARE @ExecStr NVARCHAR(4000) ,
            @Recompile BIT = 0;

        SELECT  @ExecStr = 'INSERT INTO #UserDetail
                ( UserId, UserName, Email
                )';

        SELECT  @ExecStr = @ExecStr
                + N'SELECT u.UserId, u.UserName, u.Email FROM dbo.[User] u WHERE 1=1';

        IF @userId IS NOT NULL
            OR @userId <> ''
            SELECT  @ExecStr = @ExecStr + N' AND (u.UserId = @userId)';

        IF @userId IS NULL
            BEGIN
                SET @Recompile = 1
            END

        IF @Recompile = 1
            BEGIN
                SELECT  @ExecStr = @ExecStr + N' OPTION(RECOMPILE)';
            END

        EXEC [sp_executesql] @ExecStr, N'@userId BIGINT', @userId = @userId;

        SELECT  ud.UserId, ud.UserName, ud.Email
        FROM    #UserDetail ud

    END

【问题讨论】:

  • 为什么需要动态SQL?问题是编译器无法确定从存储过程返回的列将是什么。
  • @DStanley 我需要通过 (OPTION(RECOMPILE)) sql 查询重新编译 where 条件下的特定过滤器。
  • 为什么?您遇到过哪些具体问题让您认为需要强制重新编译?听起来您正试图通过智取编译器来解决性能问题。
  • 或者为什么不每次都重新编译?编译这样一个简单的查询应该不会产生很大的开销。
  • @DStanley 是的,我想解决性能问题。当我插入 UserId 时,我只得到一条记录,我不需要重新编译和重新创建执行计划,但是当我没有搜索条件时,我需要新的执行计划。

标签: c# sql-server entity-framework stored-procedures


【解决方案1】:

看来您根本不需要动态 SQL。您提到了不每次都重新编译查询的目标,但请考虑一下您是如何实现的:

  • 创建临时表
  • 创建动态 SQL 语句(“必要”时重新编译)
  • 填写临时表
  • 从临时表中选择所有数据

因此,您的 I/O 和内存需要加倍以节省 CPU 时间的一小部分。您的存储过程似乎等同于:

CREATE PROC [SUPPORT].[GetUserDetail] @userId BIGINT
AS
    BEGIN

    SELECT u.UserId, u.UserName, u.Email 
    FROM dbo.[User] u 
    WHERE (@userId IS NULL OR u.UserId = @userId)
    OPTION(RECOMPILE)

END

如果这为您提供了所需的结果但看起来太慢,请尝试不使用 RECOMPILE 并查看是否有帮助。我非常怀疑添加临时表和动态 SQL 是否会通过节省偶尔的重新编译来提高性能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    相关资源
    最近更新 更多