代码之家  ›  专栏  ›  技术社区  ›  Adam Lassek

如何让LINQtoSQL识别动态存储过程的结果集?

  •  8
  • Adam Lassek  · 技术社区  · 17 年前

    我使用LINQtoSQL和SQLServer后端(当然)作为项目的ORM。我需要从一个从动态创建的表返回的存储过程中获取结果集。以下是程序的外观:

    CREATE procedure [RetailAdmin].[TitleSearch] (
    @isbn varchar(50), @author varchar(50),
     @title varchar(50))
    as
    
    declare @L_isbn varchar(50)
    declare @l_author varchar(50)
    declare @l_title varchar(50)
    declare @sql nvarchar(4000)
    
    set  @L_isbn = rtrim(ltrim(@isbn))
    set @l_author = rtrim(ltrim(@author))
    set @l_title = rtrim(ltrim(@title))
    
    CREATE TABLE #mytemp(
        [storeid] int not NULL,
        [Author] [varchar](100) NULL,
        [Title] [varchar](400) NULL,
        [ISBN] [varchar](50) NULL,
        [Imprint] [varchar](255) NULL,
        [Edition] [varchar](255) NULL,
        [Copyright] [varchar](100) NULL,
        [stockonhand] [int] NULL
    )
    
    set @sql  = 'select  a.storeid, Author,Title, thirteendigitisbn ISBN,  
    Imprint,Edition,Copyright ,b.stockonhand from ods.items a join ods.inventory b on     
    a.itemkey = b.itemkey where b.stockonhand <> 0  ' 
    
    if len(@l_author) > 0
    set @sql =  @sql + ' and author like ''%'+@L_author+'%'''
    
    if len(@l_title) > 0
    set @sql =  @sql + ' and title like ''%'+@l_title+'%'''
    
    if len(@L_isbn) > 0
    set @sql =  @sql + ' and thirteendigitisbn like ''%'+@L_isbn+'%'''
    
    print @sql
    
    if len(@l_author) <> 0 or len(@l_title) <>  0 or len(@L_isbn) <> 0 
    
    begin
        insert into #mytemp
        EXECUTE sp_executesql  @sql
    end 
    
    
    select * from #mytemp
    drop table #mytemp
    

    我没有编写此过程,但如果出现严重问题,可能会影响更改。

    我目前的问题是,当我将此过程添加到模型中时,设计器会生成以下函数:

    [Function(Name="RetailAdmin.TitleSearch")]
    public int TitleSearch([Parameter(DbType="VarChar(50)")] string isbn,  
      [Parameter(DbType="VarChar(50)")] string author, 
      [Parameter(DbType="VarChar(50)")] string title)
    {
        IExecuteResult result = this.ExecuteMethodCall(this, 
            ((MethodInfo)(MethodInfo.GetCurrentMethod())), isbn, author, title);
    
        return ((int)(result.ReturnValue));
    }
    

    这与我手动运行过程时得到的结果集完全不同:

    Result Set

    有人能告诉我这里出了什么问题吗?

    this question 但由于OP的措辞不当,它从未得到真正的回答。


    谢谢你的回复。我会考虑做出你建议的改变。

    问题是临时表。LinqtoSQL只是不知道如何处理它们。这尤其难以诊断,因为VisualStudio缓存有关存储过程的信息,因此当它最初未能找到结果集时,它将返回设置为默认整数类型,并且在我更改存储过程时不会更新。让VS识别更改需要您:

    • 从dbml中删除proc
    • 从服务器资源管理器中删除服务器连接
    • 保存dbml以强制重新编译
    • 重新创建服务器连接并导入进程

    2 回复  |  直到 9 年前
        1
  •  5
  •   Marc Gravell    17 年前

    首先- -您的SQL易受注入攻击;内部命令应参数化:

    if len(@l_author) > 0
    set @sql =  @sql + ' and author like ''%''+@author+''%'''
    
    EXECUTE sp_executesql  @sql, N'@author varchar(100)', @L_author
    

    @L_author 作为 @author


    第二,你并不真的需要临时表。它对你没有任何帮助。。。您只需插入并选择。也许只是执行并让结果自然地流向调用方?

    在其他情况下,表变量更合适,但这不适用于INSERT/EXEC。


    SET FMT_ONLY ON 我可以工作。

    如果不是(每个用法有不同的列),那么就没有一个简单的答案。在这种情况下,可能使用常规ADO.NET( ExecuteReader / IDataReader DataTable.Fill

    ...
    if(!string.IsNullOrEmpty(author)) {
        query = query.Where(row => row.Author.Contains(author));
    }
    ...
    

    等

        2
  •  5
  •   BFree    17 年前