Dapper - 使用嵌套对象插入
本文关键字:对象 插入 嵌套 Dapper | 更新日期: 2023-09-27 17:56:52
我有一个带有嵌套类Bank
的类User
。
class User{
int Id;
string username;
Bank bank;
}
Class Bank{
int id;
string name;
}
我需要为User
创建一个插入函数。Dapper
有没有办法执行查询并从嵌套对象绑定参数?
您可以使用 DapperExtensions 为 Dapper 编写自定义映射器:
public sealed class UserMapper : ClassMapper<User>
{
public UserMapper()
{
Map(x => x.bank.id).Column("BankId");
Map(x => x.bank.name).Column("BankName");
AutoMap();
}
}
https://github.com/tmsmith/Dapper-Extensions/wiki/Customized-mapping-for-a-class
请确保注册包含映射器的程序集:
DapperExtensions.SetMappingAssemblies(new[] { typeof(UserMapper).Assembly });
对于不仅User
对象而且List<User>
可能还需要插入数据库的情况,您可以考虑使用 table valued parameters
. 对于您的问题,它将是:
-
使用
IEnumerable<User>
和IEnumerable<Bank>
,即使只是一个对象 -
使用适当的架构和与存储过程的
IEnumerable collection
相同的columns
顺序进行TVP
,否则将导致错误 -
您可以使用
dynamic parameters
来绑定参数,对于TVP
,可以使用扩展方法提供IEnumerable
AsTableValuedParameters
如果您使用的是anonymous type
参数不是dynamic parameters
,则使用 Nuget 中FastMember
中的ObjectReader
将IEnuemrable<T>
转换为Datatable
,这对于 TVP 是必需的。即使是自定义代码也可用于IEnuemrable<T>
到Datatable
的转换,以防需要省略很少的列,以下是代码片段:
public static DataTable CreateTable<TDataTable>(this IEnumerable<TDataTable> collection)
{
// Fetch the type of List contained in the ParamValue
var tableType = typeof(TDataTable);
// Create DataTable which will contain data from List<T>
var dataTable = new DataTable();
// Fetch the Type fields count
var columnCount = tableType.GetProperties().Count();
var columnNameMappingDictionary = new Dictionary<string, string>();
// Create DataTable Columns using table type field name and their types
// Traversing through Column Collection
for (var counter = 0; counter < columnCount; counter++)
{
var propertyInfo = tableType.GetProperties()[counter];
var columnName = propertyInfo.Name;
columnNameMappingDictionary.Add(propertyInfo.Name,
propertyInfo.Name);
// Fetch the current type of a property and check whether its nullable type before adding a column
var currentType = tableType.GetProperties()[counter].PropertyType;
dataTable.Columns.Add(columnName, Nullable.GetUnderlyingType(currentType) ?? currentType);
}
// Return parameter with null value
if (collection == null)
return dataTable;
// Traverse through number of entries / rows in the List
foreach (var item in collection)
{
// Create a new DataRow
var dataRow = dataTable.NewRow();
foreach (var columnName in columnNameMappingDictionary.Select(propertyinfo => propertyinfo.Value))
{
dataRow[columnName] = item.GetType().GetProperty(columnName).GetValue(item) ?? DBNull.Value;
}
// Add Row to Table
dataTable.Rows.Add(dataRow);
}
return (dataTable);
}