65.9K
CodeProject 正在变化。 阅读更多。
Home

muSQLe - SQL Server查询调用框架

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.32/5 (9投票s)

2006 年 9 月 1 日

CPOL

4分钟阅读

viewsIcon

57700

downloadIcon

459

一种简单且强类型的从代码调用查询和存储过程的方法

Sample Usage Screenshot

引言

随着 ADO.NET 的到来,我们有了与 Microsoft SQL Server 通信的极其强大的方式。但是,调用 SQL 存储过程、函数甚至简单的查询会让你每次需要时都写出类似...的语句。

using (SqlCommand cmd = connection.CreateCommand())
{
    cmd.CommandType = CommandType.StoredProcedure; 
    cmd.CommandText = "MyProcName"; 
    cmd.Parameters.Add ( ... ); 
    .... 
    cmd.Parameters.Add ( ... ); 
    cmd.ExecuteNonQuery(); 	// or cmd.ExecuteReader() and more lines of code 
			// to read results
    			// and even more lines if Output parameters are present.
}

... 每次需要时。此外,您必须使用 DBNull.Value 而不是 C# 中的 null 或 VB 中的 Nothing(这需要额外的检查和转换)。当然,您可以为每个查询编写大量包装器并将它们用作内置函数,但我认为这不是很方便。

背景

此项目的核心部分是 SqlQuery 类。它继承自 RealProxy,用于包装声明了 SQL 函数的接口。SqlImportAttribute 属性用于将方法标记为 SQL 方法。它还可以指定函数名称或查询类型和文本。

当方法被调用时,代理会在由内部 static SqlParameterCache 类表示的缓存中查找它。当找到缓存条目(即此方法已被解析)时,它会返回给代理。否则,它将使用反射从 MethodInfo 定义中解析。同时还会执行一些基本检查。

  • SqlReturnAttribute 属性每个方法定义只能使用一次。
  • 标记了 SqlReturnAttribute 的参数必须是 out 参数,并且类型为 classNullable<>
  • 如果方法的返回类型被标记为 SqlReturnAttribute,则它必须是 classNullable<> 类型。
  • ref 参数被解释为 InputOutput SQL 参数,out 参数被解释为 Output。两者都必须是 classNullable<> 类型。
  • Output 参数必须指定 SqlTypeAttribute

当所有这些检查通过后,SqlParameterCacheEntry 实例将被存储在缓存中并传回给代理。如果任何检查失败,则会抛出 ArgumentException

然后代理创建并初始化 SqlCommand 类的一个实例,用传入的参数填充所有需要的参数,并执行命令。执行的类型由方法定义确定。

  • 如果方法返回类型为 voidint 或标记了 SqlReturnAttribute,则使用 ExecuteNonQuery()
  • 如果方法的返回类型为 DataSet,则使用 ExecuteReader()
  • 如果方法的返回类型为 DataTable,则使用 ExecuteReader(CommandBehavior.SingleResult)
  • 如果方法的返回类型为 SingleRowDataTable,则使用 ExecuteReader(CommandBehavior.SingleResult | CommandBehavior.SingleRow)

SingleRowDataTable 类继承自 DataTable,主要用于类型区分。它还提供了一个 Row 属性来访问第一行(如果不存在,则返回 null)。

用法

首先,您需要声明一个包含方法定义的 Interface。通用方法描述。

  1. 每个方法定义都以 [SqlImport] 开始。它可以不带参数。
    • 如果方法名称与存储过程/函数名称不同,则必须在参数中指定真实名称:[SqlImport("realname")]
    • 如果方法用于包装另一种类型的查询(表直接查询、SQL 查询),则还必须指定查询类型:[SqlImport(CommandType.TableDirect, "tableName")]
  2. 然后是返回类型定义。
    • 对于不返回任何表数据(或我们不关心)的存储过程,我们应该使用以下类型之一:
      • void
      • int(返回调用受影响的行数)
      • 标记了 [return: SqlReturn] 的可空类型 - 存储过程或函数的返回值。例如:[return: SqlReturn] int?
      • 标记了 [return: SqlReturn("ParamName")] 的可空类型 - 存储过程的输出参数。例如:[return: SqlReturn("ParamName"), SqlType(SqlDbType.Int)] int?
    • 当存储过程返回表数据时,应使用 DataSetDataTableSingleRowDataTable 类型。
  3. 从您的代码中调用的方法名称。
  4. 参数。[SqlReturn] 属性也可以应用于 out 参数。[SqlType] 属性必须应用于每个 out 参数。

可以通过 XML 注释(如图所示)将帮助文本和描述应用于方法。

示例

// Interface definition:

interface IQuerySample
{
    /// <summary>
    /// Returns a list of active sessions on server
    /// </summary>
    /// <param name="LogiName">Show sessions only for this user, 
    /// null - for all users</param>
    /// <returns>DataTable with session info</returns>
    [SqlImport("sp_who")]
    DataTable ShowSessions(string LogiName);
}

// Usage: 
// Let's fill DataGridView named 'grid' with session information.
// Don't forget to turn on AutoGenerateColumns property.

// ...
IQuerySample q = SqlQuery<IQuerySample>.Create(connection);
grid.DataSource = q.ShowSessions(null);
// ... Here we could use 'q' more and more times ...

很简单,不是吗?

版本历史

  • 9.09.06. 
    • Create 方法添加了新的重载,允许从连接字符串创建查询。使用此重载时,连接将在执行查询之前打开,并在之后关闭。还添加了 NullableEnum<T> static 类,以帮助将可空的数字查询结果与 enum 值进行转换。
  • 7.09.06. 
    • 修复了输出参数中 NULL 值作为方法结果返回的错误。添加了更详细的异常描述。
  • 6.09.06.
    • 修复了 out 参数的错误。添加了 SqlTypeAttribute 属性用于显式类型指定。向 SqlReturnAttribute 添加了可选参数,允许方法不仅返回返回值,还可以返回 out 参数。因此,您可以编写 [return: SqlReturn("ParamName")] 来返回输出参数 ParamName 的值,这对于返回例如新创建记录 ID 的存储过程非常有用。
  • 1.09.06.
    • 首次发布
© . All rights reserved.