DRY CLR表值函数

时间:2011-06-21 14:26:04

标签: c# .net sql-server sqlclr user-defined-functions

我正在使用CLR table-valued function来SELECT并返回使用许多变量的复杂数据库搜索的结果。

文档显示您以类似于此的方式构建此类函数:

public partial class UserDefinedFunctions
{
    private class ResultRow
    // This class holds a row which we want to return.
    {
        public SqlInt32 CustId;
        public SqlString Name;

        public ResultRow(SqlInt32 custId_, SqlString name_)
        {
            CustId = custId_;
            Name = name_;
        }
    }

    [SqlFunction(
        DataAccess = DataAccessKind.Read,
        FillRowMethodName = "Test_FillRow",
        TableDefinition = "CustId int" +
                          "Name nvarchar(50)")]
    public static IEnumerable Test()
    // This function contains the actual logic.
    {
        ArrayList results = new ArrayList();

        using (SqlConnection connection = new SqlConnection("context connection=true"))
        {
            connection.Open();

            using (SqlCommand select = new SqlCommand(
                "SELECT TOP 100 custid, name FROM Customers",
                connection))
            {
                using (SqlDataReader reader = select.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        results.Add(new ResultRow(
                            reader.GetSqlInt32(0),  // CustId
                            reader.GetSqlString(1)  // Name
                        ));
                    }
                }
            }
        }
        return results;
    }

    public static void Test_FillRow(
        object resultsObj,
        out SqlInt32 custid,
        out SqlString name)
    // This function takes a row and tells SQL Server what variables we want to 
    // return from it and what types it contains.
    {
        ResultRow selectResults = (ResultRow)resultsObj;

        custid = selectResults.CustId;
        name = selectResults.Name;
    }
}

问题是,它相当重复。首先在SqlFunction块中定义表。然后,当您在返回的结果中添加或删除列时,您必须确保更新它并

  • ResultRow中的定义
  • ResultRow
  • 中构造函数的参数
  • ResultRow中的作业
  • 在Test()
  • 中从阅读器中获取的类型
  • Test_FillRow()
  • 中的out参数
  • Test_FillRow()
  • 中的分配
  • 和SQL查询本身,这是你真正想要开始考虑的唯一部分。

我正在研究这样一个函数,它接受20多个参数,返回更多行,并包含这8个可能出错的地方。 。所有的错误都是微不足道的,很容易修复,但是很容易修复,因为代码中有很多地方需要手动保持同步。

这是对DRY的违反,但我不知道如何消除重复。是否有更简洁的方法来编写CLR表值函数?

2 个答案:

答案 0 :(得分:0)

如果将参数集设置为类,则可以使用约束在其基类上的泛型方法来实现数据访问。我经常发现一个用于传递组中参数的类,通常会在其他地方找到有用的内容以及重构。

将20个参数传递给函数通常不是一个好主意。

这是一个很好的总结,我通常同意函数参数: http://benbiddington.wordpress.com/2009/06/22/book-review-of-clean-code/

具体做法是:

  

如果函数需要两个或三个以上的参数,那很可能   至少其中一些应该包装在他们自己的类中。

在这种情况下,这样做的好处可能是提取一些通用方法,这些方法可以帮助您更紧密地遵守DRY。

答案 1 :(得分:0)

如果用对象[]替换ResultRow,则可以使用reader.GetValues(object [])并消除必须知道行中的内容,直到FillRow(),然后FillRow负责知道字段的顺序是什么在原始查询中。

这真的是一种权衡,你可以放弃一直强大的打字,换取不必一直做强打字,但很难两种方式: - )