确定是否从架构生成ExecuteNonQuery或ExecuteReader

时间:2009-09-24 03:42:28

标签: c# sql-server stored-procedures ado.net schema

我正在尝试创建一个存储过程/ ADO.NET映射机制,其中带参数的存储过程变为

object MyStoredProcedure.Execute(out returnValue, param1, param2, ...) 

尝试生成实际的数据检索方法时出现问题。我可以从Information Schema视图中轻松获取我需要的大部分模式信息,但是我无法可靠地找到应该来自过程的返回类型(输出参数与SELECT / SqlDataReader相对于两者)以及是否调用ExecuteNonQuery或者ExecuteReader。

最糟糕的情况是,我可以解析程序的文本,但有各种各样的时髦的东西可能会出错。

代码生成的原因是应用程序数据库包含数百个存储过程。我们继承了这个项目,所以没有办法围绕我们没有创建的许多过程。

实际上,ADO.NET生成有两个主要目标:

1)从应用程序中删除所有字符串文字(SqlCommand创建中存储的proc名称,SqlParameter创建中的参数名称等)。这样,当过程或数据库模式发生更改时,我们可以重新生成ADO.NET包装器,并且这些更改产生的任何错误都将在编译时捕获。

2)删除了挖掘proc以确定params,返回类型等的需要。基本上,数据库本身就变成了一个API,所有内部存储过程细节都被抽象掉了。

5 个答案:

答案 0 :(得分:3)

烨;这并不容易。对于简单的情况,您可以尝试运行sp(awooga!)为所有参数传递空值,并使用SET FMTONLY ON - 有点冒险(例如,执行扩展的sprocs)而不是因为TSQL可以在输入上进行分支。但是一个选择。

“out”ets应该可以通过元数据获得; “旧”的方式是syscolumns(可能有一种信息模式替代方法,以正确的方式)。


就像更新一样;如果您希望数据库将自己描述为API,可以考虑选择UDF;优点:

  • 返回值的元数据是严格且易于查询的
  • 可以在来电者处理

或者;只需使用ORM。 LINQ-to-SQL可以很好地使用这种类型的设置(包括可组合性);实体框架肯定会为您的存储过程做一切艰苦的工作。或任何其他人; NHibernateLLBLGen Pro等等。他们都解决了这个问题。这不是微不足道的;为什么重新发明它?

答案 1 :(得分:2)

我认为你不应该担心它 提供超载并不是更好吗?让用户决定调用哪种方法?

如果我没有正确理解这个问题,请告诉我。

答案 2 :(得分:0)

假设所有存储过程都是一致的,也就是说,每个存储过程最多返回一个结果集,具有相同的列集,而不管它的参数值或数据库的数据状态,并且所有OUTPUT参数都是总是写到,..

并且还假设这是一个开发或最近的构建时工具(并且不是运行时工具)并且您可以控制Srored Procedure的内容,那么这里是我会尝试的:

  1. 制定追溯存储过程标准,要求所有sProcs都要对以下形式发表评论,这些评论必须在测试(或开发?)数据库中正常工作:

    'TEST:EXEC spThisProc [,...]

  2. 编写工具以从系统目录中提取存储过程及其参数,数据类型和输出参数的列表(您可以使用INFORMATION_SCHEMA表ROUTINES和PARAMETERS)。

  3. 还检索所有sProcs的脚本(来自INFORMATION_SCHEMA.ROUTINES表的ROUTINE_DEFINITON列,一个地方),然后提取“'TEST:”命令(上面)和ExecuteReader的文本。测试数据库。然后测试返回的Resultset以查看它是否包含任何数据集(或者它是“Tables”?)。如果没有,则将此sProc标记为需要ExecuteNonQuery,否则,提取返回的数据集的列定义,并使用than为类定义生成相应的ExecuteReader代码。

答案 3 :(得分:0)

希望这有助于检索params的类型

  select s.id, s.name, t.name as [type], t.length,s.isoutparam
  from syscolumns s inner join systypes t 
  on s.xtype = t.xtype 
  where id = (select id from sysobjects where name =  'SP NAME')

并查看这个优秀的链接 - get the list of columns returned from the SQL select

这是一个示例查询

USE tempdb
GO

IF OBJECT_ID('dbo.TestSP') IS NOT NULL
        DROP PROCEDURE dbo.TestSP;
GO

IF NOT EXISTS (SELECT * FROM sys.servers WHERE name = 'Loopback')
BEGIN
        EXEC sp_addlinkedserver @server = 'Loopback',  @srvproduct = '',
                                           @provider = 'SQLOLEDB', @datasrc = @@servername
END
GO

CREATE PROC dbo.TestSP
AS
        SELECT 1 as [ID], 'Name' as [Name], 'Boston' as [City]
GO

DECLARE @MyXML XML
SELECT @MyXML = (SELECT * FROM
        (SELECT * 
        FROM OPENQUERY(Loopback,'SET FMTONLY ON; 
                  EXEC tempdb.dbo.TestSP; 
                  SET FMTONLY OFF')) vw FOR XML AUTO, XMLSCHEMA)

SELECT @MyXML

SET FMTONLY - >它将允许您运行SP,但只返回元数据

答案 4 :(得分:0)

此外,您可以尝试查看SqlServer SMO http://msdn.microsoft.com/en-us/library/ms162169.aspx以查询有关数据库的信息,而无需直接针对信息架构编写查询。