DRY CLR табличные функции - PullRequest
5 голосов
/ 21 июня 2011

Я использую табличную функцию CLR , чтобы ВЫБРАТЬ и вернуть результаты сложного поиска в базе данных, который использует много переменных.

Документация показывает, что вы строите такую ​​функциюпримерно так:

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 ()
  • назначения в Test_FillRow()
  • и сам SQL-запрос, который является единственной частью, с которой вы действительно пытаетесь начать.

Я работаю над такой функцией, которая принимаетболее двадцати аргументов, возвращает еще больше строк и содержит эти восемь возможных мест для ошибок. Восемь .Все ошибки тривиальны и легко исправимы, но их очень легко сделать, потому что в коде так много мест, которые я должен вручную синхронизировать.

Это нарушение DRY, но я нене знаю, как устранить повторение.Есть ли более краткий способ написания табличных функций CLR?

Ответы [ 2 ]

0 голосов
/ 29 декабря 2011

Если вы замените свой ResultRow на object [], вы можете использовать reader.GetValues ​​(object []) и избавиться от необходимости знать, что находится в строках, до FillRow (), а затем FillRow отвечает за знание порядка полей.в исходном запросе.

Это действительно компромисс, вы можете отказаться от строгой типизации до конца, в обмен на то, что нет необходимости выполнять строгую типизацию до конца, но трудно иметь и то, и другое.способы: -)

0 голосов
/ 21 июля 2011

Если вы превратили свои наборы параметров в классы, вы можете использовать универсальный метод, ограниченный их базовым классом, для реализации доступа к данным. Я обнаружил, что обычно класс, используемый для передачи параметров в группах, как обычно, будет полезен и в других местах, а также при рефакторинге.

Как правило, никогда не рекомендуется передавать функции двадцать параметров.

Вот хорошее резюме, с которым я обычно согласен в отношении аргументов функции: http://benbiddington.wordpress.com/2009/06/22/book-review-of-clean-code/

В частности:

Если функция ожидает более двух или трех аргументов, вероятно, что по крайней мере некоторые из них должны быть обернуты в их собственный класс.

В этом случае выгода от этого, вероятно, может заключаться в извлечении некоторых общих методов, которые помогут вам более строго придерживаться DRY.

...