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有没有办法执行查询并从嵌套对象绑定参数?

Dapper - 使用嵌套对象插入

您可以使用 DapperExtensionsDapper 编写自定义映射器:

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 中的ObjectReaderIEnuemrable<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);
}