gpt4 book ai didi

c# - 如何让 Linq to SQL 识别动态存储过程的结果集?

转载 作者:太空狗 更新时间:2023-10-29 18:28:30 25 4
gpt4 key购买 nike

我将 Linq-to-SQL 与 SQL Server 后端(当然)一起用作项目的 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));
}

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

Result Set

谁能告诉我这里出了什么问题?

这基本上是与this question 相同的问题但由于 OP 的措辞不佳,从未真正回答过。


感谢马克的回复。我会考虑进行您建议的更改。

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

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

您可能不必执行其中的每一个步骤,但这对我来说很有效。如果您必须使用临时表,您需要做的是创建一个仅返回正确模式的准系统过程,然后在将其导入 OR Designer 后更改它以执行您想要的操作。

最佳答案

首先 - 重要 - 你的 SQL 容易被注入(inject);内部命令应该参数化:

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 参数传递 - 防止注入(inject)攻击。


其次 - 您实际上并不需要临时表。它对你没有任何作用……你只是插入和选择。也许只是执行并让结果自然地流向调用者?

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


每次调用的列是否相同?如果是这样,要么手动编写 dbml,要么使用临时 SP(只需使用“WHERE 1=0”或其他东西)以便 SET FMT_ONLY ON 可以工作。

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

当然,您可以让 LINQ 承担压力...(C#):

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

等等

关于c# - 如何让 Linq to SQL 识别动态存储过程的结果集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/496195/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com