DRY CLR表值函数

我正在使用CLR表值函数来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多个参数,返回更多行,并包含这八个可能出错的地方。 。 所有的错误都是微不足道的,很容易修复,但它很容易制作,因为代码中有很多地方我必须手动保持同步。

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

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

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

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

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

这是一个很好的总结,我通常在function参数上达成一致: http : //benbiddington.wordpress.com/2009/06/22/book-review-of-clean-code/

特别:

如果函数需要两个或三个以上的参数,那么至少其中一些参数应该包含在它们自己的类中。

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