Хтось знає, чи можна передавати дані параметрів, що мають значення таблиці, до збереженої процедури за допомогою Dapper?
Хтось знає, чи можна передавати дані параметрів, що мають значення таблиці, до збереженої процедури за допомогою Dapper?
Відповіді:
Зараз існує (n Dapper 1.26 і вище) пряма підтримка табличних параметрів, запечених у dapper. У випадку збережених процедур, оскільки тип даних вбудований в API sproc, все, що вам потрібно зробити, це надати 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
}, ...);
Будь-яка з них повинна працювати нормально.
ExecuteReader
, я отримую, "Події-члени типу System.Data.DataTable не можуть використовуватися як значення параметра".
Так, ми їх підтримуємо, але вам потрібно буде запрограмувати власних помічників.
Наприклад:
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, це було значно повільніше, ніж передача в декількох параметрах.
Я абсолютно не проти того, щоб у проекті contrib існували певні помічники SQL Server для dapper, однак основний dapper уникає додавання конкретних трюків постачальника, де це можливо.
Я знаю, що цей квиток є СТАРИМ, дуже старим, але хотів би повідомити, що я опублікував пакет 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.
Насолоджуйтесь!
сьогодні це не так. Ми фактично досліджували таблично-valed-параметри для нашої нахабної реалізації "in" ( where col in @values
), але нас це не вразило. Однак у контексті SPROC це має сенс.
Найкраще - зареєструвати це як випуск на сайті проекту щоб ми могли відстежувати / розставляти пріоритети. Здається, щось буде здійсненно, однак, можливо, подібне до параметрів DbString або DynamicParameters.
Але сьогодні? Ні.