Поддерживает ли Dapper поддержку табличных значений SQL 2008?

Кто-нибудь знает, можно ли передать табличный параметр данные в хранимую процедуру с помощью Dapper?

Ответ 1

Теперь (n Dapper 1.26 и выше) имеется прямая поддержка табличных параметров, запеченных в dapper. В случае хранимых процедур, поскольку тип данных встроен в sproc API, все, что вам нужно сделать, это предоставить DataTable:

var data = connection.Query<SomeType>(..., new {
    id=123, name="abc", values = someTable
}, ...);

Для прямого командного текста у вас есть еще два варианта:

  • используйте вспомогательный метод, чтобы указать тип пользовательских данных:

    var data = connection.Query<SomeType>(..., new {
        id=123, name="abc", values = someTable.AsTableValuedParameter("mytype")
    }, ...);
    
  • сообщите самой таблице данных, какой пользовательский тип данных использовать:

    someTable.SetTypeName("mytype");
    var data = connection.Query<SomeType>(..., new {
        id=123, name="abc", values = someTable
    }, ...);        
    

Любое из них должно работать нормально.

Ответ 2

Да, мы поддерживаем их, но вам нужно будет закодировать своих помощников.

Например:

class IntDynamicParam : Dapper.SqlMapper.IDynamicParameters
{
    IEnumerable<int> numbers;
    public IntDynamicParam(IEnumerable<int> numbers)
    {
        this.numbers = numbers;
    }

    public void AddParameters(IDbCommand command)
    {
        var sqlCommand = (SqlCommand)command;
        sqlCommand.CommandType = CommandType.StoredProcedure;

        List<Microsoft.SqlServer.Server.SqlDataRecord> number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();

        // Create an SqlMetaData object that describes our table type.
        Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };

        foreach (int n in numbers)
        {
            // Create a new record, using the metadata array above.
            Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
            rec.SetInt32(0, n);    // Set the value.
            number_list.Add(rec);      // Add it to the list.
        }

        // Add the table parameter.
        var p = sqlCommand.Parameters.Add("@ints", SqlDbType.Structured);
        p.Direction = ParameterDirection.Input;
        p.TypeName = "int_list_type";
        p.Value = number_list;

    }
}

// SQL Server specific test to demonstrate TVP 
public void TestTVP()
{
    try
    {
        connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)");
        connection.Execute("CREATE PROC get_ints @ints int_list_type READONLY AS select * from @ints");

        var nums = connection.Query<int>("get_ints", new IntDynamicParam(new int[] { 1, 2, 3 })).ToList();
        nums[0].IsEqualTo(1);
        nums[1].IsEqualTo(2);
        nums[2].IsEqualTo(3);
        nums.Count.IsEqualTo(3);
        connection.Execute("DROP PROC get_ints");
        connection.Execute("DROP TYPE int_list_type");

    }
}

Убедитесь, что вы правильно проверяете производительность для параметров, оцененных по таблице. Когда я тестировал это для передачи списков int, он был значительно медленнее, чем передача нескольких параметров.

Я полностью не против наличия некоторых специальных помощников SQL Server для dapper в проекте Contrib, но основной dapper избегает добавления специальных трюков поставщика, где это возможно.

Ответ 3

Я знаю, что этот билет OLD, очень старый, но хотел сообщить вам, что я опубликовал пакет Dapper.Microsoft.Sql, который поддерживает общие TVP.

https://www.nuget.org/packages/Dapper.Microsoft.Sql/

Использование примера:

List<char> nums = this.connection.Query<char>(
  "get_ints", 
  new TableValuedParameter<char>(
    "@ints", "int_list_Type", new[] { 'A', 'B', 'C' })).ToList();

Он основан на исходных классах из тестового проекта Dapper.

Наслаждайтесь!

Ответ 4

сегодня это не так. Мы действительно исследовали табличные параметры для нашей нахальной "в" реализации (where col in @values), но были очень не впечатлены производительностью. Однако в контексте SPROC это имеет смысл.

Лучше всего зарегистрировать это как проблему на сайте проекта, чтобы мы могли отслеживать/приоритизировать его. Похоже, что что-то будет выполнимо, хотя, вероятно, похоже на параметры DbString или DynamicParameters.

Но сегодня? Нет.