Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何让LINQtoSQL识别动态存储过程的结果集?_C#_Sql_Sql Server_Linq To Sql_Stored Procedures - Fatal编程技术网

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

C# 如何让LINQtoSQL识别动态存储过程的结果集?,c#,sql,sql-server,linq-to-sql,stored-procedures,C#,Sql,Sql Server,Linq To Sql,Stored Procedures,我使用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) declar

我使用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
这与我手动运行过程时得到的结果集完全不同:

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

这基本上与OP的问题相同,但由于OP的措辞不当,它从未真正得到回答


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

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

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

你可能不必每一步都做,但这对我来说是有效的。如果必须使用临时表,您需要做的是创建一个简单的过程,该过程只返回正确的模式,然后在将其导入或设计器后更改它以执行您想要的操作。

没有真正简单的方法可以做到这一点。我过去也有过同样的问题。我认为问题在于LINQtoSQL无法“计算”将返回哪种类型,因为您在执行时正在构建SELECT语句。我所做的就是在存储过程中,选择并选择所有可能需要的列。然后,我让Linq以Sql为基础生成函数。然后,我回到了SQL,并将存储过程改回了它应该的方式。这里的诀窍是不要重新生成DBML

首先-重要-您的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


每个调用的列是否相同?如果是这样,可以手动写入dbml,也可以使用临时SP(仅带有“WHERE 1=0”或其他内容),以便
SET FMT_ONLY ON
可以工作

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

当然,你可以让LINQ承受压力。。。(三):


etc

前两点对于这个特定的问题很重要,但一般来说,我认为当LINQ to SQL生成的代码没有返回预期结果时,[设置FMTONLY ON][是问题的核心部分。在某些情况下,我将其设置为OFF[当我知道存储的过程不会对数据产生任何影响时,即仅选择]。
if len(@l_author) > 0
set @sql =  @sql + ' and author like ''%''+@author+''%'''

EXECUTE sp_executesql  @sql, N'@author varchar(100)', @L_author
...
if(!string.IsNullOrEmpty(author)) {
    query = query.Where(row => row.Author.Contains(author));
}
...