C# 确定是从架构生成ExecuteOnQuery还是ExecuteReader

C# 确定是从架构生成ExecuteOnQuery还是ExecuteReader,c#,sql-server,stored-procedures,ado.net,schema,C#,Sql Server,Stored Procedures,Ado.net,Schema,我正在尝试创建一个存储过程/ADO.NET映射机制,其中包含参数的存储过程将成为 object MyStoredProcedure.Execute(out returnValue, param1, param2, ...) 当试图生成实际的数据检索方法时,问题就出现了。我可以很容易地从信息模式视图中获得所需的大多数模式信息,但我无法可靠地找到过程中应该返回的类型(输出参数vs.SELECT/SqlDataReader vs.两者),以及是调用ExecuteOnQuery还是ExecuteRe

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

object MyStoredProcedure.Execute(out returnValue, param1, param2, ...) 
当试图生成实际的数据检索方法时,问题就出现了。我可以很容易地从信息模式视图中获得所需的大多数模式信息,但我无法可靠地找到过程中应该返回的类型(输出参数vs.SELECT/SqlDataReader vs.两者),以及是调用ExecuteOnQuery还是ExecuteReader

最糟糕的情况是,我可能可以解析过程的文本,但那里有各种各样可能出错的古怪事情

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

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

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

2) 不再需要通过proc来确定参数、返回类型等。因此,基本上,数据库本身成为一个API,所有内部存储过程细节都被抽象掉了。

是的;这并不容易。对于简单的情况,您可以尝试运行sp(awooga!),为所有参数传递null,并使用-有点风险(例如,扩展存储过程是stll执行的),而且不健壮,因为TSQL可能会在输入上分支。但这是一种选择

“out”ets应通过元数据提供;“旧”方法是
syscolumns
(可能有一种信息模式替代方法可以正确地执行此操作)


作为更新;如果您希望数据库将自身描述为API,则可以考虑UDF用于选择;优点:

  • 返回值的元数据是严格的,易于查询
  • 它在调用者处是可组合的
或;只需使用ORM。LINQtoSQL将很好地使用这种类型的设置(包括可组合性);实体框架肯定会为您完成存储过程的所有艰苦工作。或任何其他人,他们都解决了这个问题。这不是小事;为什么要重新发明它?

是的;这并不容易。对于简单的情况,您可以尝试运行sp(awooga!),为所有参数传递null,并使用-有点风险(例如,扩展存储过程是stll执行的),而且不健壮,因为TSQL可能会在输入上分支。但这是一种选择

“out”ets应通过元数据提供;“旧”方法是
syscolumns
(可能有一种信息模式替代方法可以正确地执行此操作)


作为更新;如果您希望数据库将自身描述为API,则可以考虑UDF用于选择;优点:

  • 返回值的元数据是严格的,易于查询
  • 它在调用者处是可组合的

或;只需使用ORM。LINQtoSQL将很好地使用这种类型的设置(包括可组合性);实体框架肯定会为您完成存储过程的所有艰苦工作。或任何其他人,他们都解决了这个问题。这不是小事;为什么要重新发明它?

我认为你不应该担心它。
提供重载不是更好吗&让用户决定调用哪个方法


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

我认为你不应该为此担心。
提供重载不是更好吗&让用户决定调用哪个方法


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

假设您的所有存储过程都是一致的,即每个存储过程最多返回一个结果集,且具有相同的列集,而不管其参数值或数据库的数据状态如何,并且所有输出参数始终写入

并且还假设这是一个开发工具,或者至少是一个构建时工具(而不是运行时工具),并且您可以控制存储过程的内容。。下面是我要尝试的:

  • 制定一个追溯存储过程标准,要求所有存储过程都有以下形式的注释,这些注释必须在测试(或开发?)数据库中正常工作:

    '测试:EXEC spThisProc[,…]

  • 编写工具以从系统目录中提取存储过程列表、其参数、数据类型和输出参数(您可以为此使用信息\u SCHEMA tables例程和参数)

  • 还要检索所有存储过程的脚本(从INFORMATION_SCHEMA.ROUTINES表的ROUTINE_DEFINITON列中,一个位置),然后提取“'TEST:”命令(如上)的文本,并针对测试数据库执行该命令。然后测试返回的结果集,看看它是否包含任何数据集(或者是“表”)。如果没有,则将此存储过程标记为需要ExecuteOnQuery,否则,提取返回数据集的列定义,并使用than为类定义生成相应的ExecuteReader代码


  • 假设您的所有存储过程都是一致的,也就是说,每个存储过程最多返回一个结果集,且具有相同的列集,而不管其参数值或数据库的数据状态如何,并且所有输出参数始终写入

    并且还假设这是一个开发工具,或者至少是一个构建时工具(而不是运行时工具),并且您可以控制存储过程的内容。。下面是我要尝试的:

  • 建立一个追溯存储过程标准,该标准要求所有sPro
      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')
    
    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