C# 这是使用Dapper进行批量插入的有效方法吗?
这是使用Dapper进行批量插入的有效方法吗 此外,这是否比创建存储过程并向其传递模型更有效C# 这是使用Dapper进行批量插入的有效方法吗?,c#,.net,database,insert,dapper,C#,.net,Database,Insert,Dapper,这是使用Dapper进行批量插入的有效方法吗 此外,这是否比创建存储过程并向其传递模型更有效 category = new Category { Name = "category", Description = "description", Created = null, LastM
category = new Category
{
Name = "category",
Description = "description",
Created = null,
LastModified = null,
CategoryPictures = new CategoryPicture[]
{
new CategoryPicture
{
CategoryId = 3,
PictureId = 2,
Picture = new Picture
{
Url = "newUrl"
}
},
new CategoryPicture
{
CategoryId = 3,
PictureId = 2,
Picture = new Picture
{
Url = "url"
}
}
}
};
string sql = @"INSERT INTO Categories(Name, Description, Created, LastModified)
VALUES(@Name, @Description, @Created, @LastModified)";
await conn.ExecuteAsync(sql, new
{
category.Name,
category.Description,
category.Created,
category.LastModified
});
string catPicInsert = @"INSERT INTO CategoryPictures(fk_CategoryId, fk_PictureId)
VALUES(@CategoryId, @PictureId)";
await conn.ExecuteAsync(catPicInsert, category.CategoryPictures);
string PicInsert = @"INSERT INTO Pictures(Url)
VALUES(@Url)";
await conn.ExecuteAsync(PicInsert, category.CategoryPictures.Select(x =>
x.Picture).ToList());
这是使用Dapper进行批量插入的有效方法吗?
此外,这是否比创建存储过程并向其传递模型更有效
category = new Category
{
Name = "category",
Description = "description",
Created = null,
LastModified = null,
CategoryPictures = new CategoryPicture[]
{
new CategoryPicture
{
CategoryId = 3,
PictureId = 2,
Picture = new Picture
{
Url = "newUrl"
}
},
new CategoryPicture
{
CategoryId = 3,
PictureId = 2,
Picture = new Picture
{
Url = "url"
}
}
}
};
string sql = @"INSERT INTO Categories(Name, Description, Created, LastModified)
VALUES(@Name, @Description, @Created, @LastModified)";
await conn.ExecuteAsync(sql, new
{
category.Name,
category.Description,
category.Created,
category.LastModified
});
string catPicInsert = @"INSERT INTO CategoryPictures(fk_CategoryId, fk_PictureId)
VALUES(@CategoryId, @PictureId)";
await conn.ExecuteAsync(catPicInsert, category.CategoryPictures);
string PicInsert = @"INSERT INTO Pictures(Url)
VALUES(@Url)";
await conn.ExecuteAsync(PicInsert, category.CategoryPictures.Select(x =>
x.Picture).ToList());
它不会非常慢,但也不会像批量拷贝那么快。选项,假设SQL Server:
- 可以将TVPs与Dapper一起使用,但唯一方便的方法是将输入数据打包到
;在Dapper repo中有使用TVP的例子,或者我可以删掉一个,但是它们很不方便,因为您需要在服务器上声明参数类型数据表中
- 您可以使用
独立于Dapper将数据放入数据库;FastMember具有SqlBulkCopy
,可以在键入的序列上构造ObjectReader
,适合与IDataReader
SqlBulkCopy
如果不使用SQL Server,则需要查看RDBMS的特定于供应商的选项。我已将其更改为对每个表使用多个存储过程
public async Task<bool> CreateCategoryAsync(Category category)
{
category = new Category
{
Name = "category",
Description = "description",
Created = null,
LastModified = null,
CategoryPictures = new CategoryPicture[]
{
new CategoryPicture
{
CategoryId = 1,
PictureId = 2,
Picture = new Picture
{
Url = "newUrl"
}
},
new CategoryPicture
{
CategoryId = 2,
PictureId = 2,
Picture = new Picture
{
Url = "url"
}
}
}
};
string sql = @"EXEC Categories_Insert @Categories;
EXEC CategoryPictures_Insert @CategoryPictures;
EXEC Pictures_Insert @Pictures";
var spParams = new DynamicParameters(new
{
Categories = category.ToDataTable().AsTableValuedParameter("CategoriesType"),
CategoryPictures = category.CategoryPictures.ListToDataTable()
.AsTableValuedParameter("CategoryPictureType"),
Pictures = category.CategoryPictures.Select(x => x.Picture)
.ListToDataTable()
.AsTableValuedParameter("PicturesType")
});
using (var conn = SqlConnection())
{
using (var res = await conn.QueryMultipleAsync(sql, spParams))
{
return true;
}
}
}
公共异步任务CreateCategoryAsync(类别)
{
类别=新类别
{
Name=“category”,
Description=“Description”,
Created=null,
LastModified=null,
CategoryPictures=新的CategoryPicture[]
{
新类别结构
{
类别ID=1,
PictureId=2,
图片=新图片
{
Url=“newUrl”
}
},
新类别结构
{
类别ID=2,
PictureId=2,
图片=新图片
{
Url=“Url”
}
}
}
};
字符串sql=@“EXEC Categories_Insert@Categories;
EXEC CategoryPictures_Insert@CategoryPictures;
EXEC Pictures_Insert@Pictures”;
var spParams=新的动态参数(新的
{
Categories=category.ToDataTable().AsTableValuedParameter(“CategoriesType”),
CategoryPictures=category.CategoryPictures.ListToDataTable()
.AsTableValuedParameter(“类别类型”),
Pictures=category.CategoryPictures.Select(x=>x.Picture)
.ListToDataTable()
.AsTableValuedParameter(“图片类型”)
});
使用(var conn=SqlConnection())
{
使用(var res=await conn.QueryMultipleAsync(sql,spParams))
{
返回true;
}
}
}
这是我为将对象或对象列表映射到Datatable而创建的带有泛型方法的扩展类
public static class DataTableExtensions
{
/// <summary>
/// Convert an IEnumerable into a Datatable
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="listToDataTable"></param>
/// <returns></returns>
public static DataTable ListToDataTable<T>(this IEnumerable<T> listToDataTable)
{
DataTable dataTable = new DataTable();
AddToDataTableColumns<T>(dataTable);
foreach (var item in listToDataTable)
{
AddDataTableRows(dataTable, item);
}
return dataTable;
}
/// <summary>
/// Comvert a Type of Class to DataTable
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static DataTable ToDataTable<T>(this T obj) where T : class
{
DataTable dataTable = new DataTable();
AddToDataTableColumns<T>(dataTable);
AddDataTableRows(dataTable, obj);
return dataTable;
}
/// <summary>
/// Add values from of Type T to a given Datatable columns
/// </summary>
/// <typeparam name="T">Extract values from</typeparam>
/// <param name="dataTable">The datatable to add column values into</param>
/// <returns></returns>
private static DataTable AddToDataTableColumns<T>(DataTable dataTable)
{
try
{
PropertyInfo[] FilteredProps = GetFilteredProperties(typeof(T));
for (int i = 0; i < FilteredProps.Length; i++)
{
PropertyInfo prop = FilteredProps[i];
Type type = prop.PropertyType;
dataTable.Columns.Add(prop.Name, Nullable.GetUnderlyingType(type) ?? type);
}
}
catch (Exception ex)
{
new InfrastructuredException(ex.StackTrace);
}
return dataTable;
}
/// <summary>
/// Add values from of Type T to a given Datatable Rows
/// </summary>
/// <typeparam name="T">Extract values from</typeparam>
/// <param name="dataTable">The datatable to add Row values into</param>
/// <returns></returns>
private static DataTable AddDataTableRows<T>(DataTable dataTable, T obj)
{
try
{
PropertyInfo[] FilteredProps = GetFilteredProperties(typeof(T));
object[] values = new object[FilteredProps.Length];
for (int i = 0; i < values.Length; i++)
{
values[i] = FilteredProps[i].GetValue(obj);
}
dataTable.Rows.Add(values);
}
catch (Exception ex)
{
new InfrastructuredException(ex.StackTrace);
}
return dataTable;
}
/// <summary>
/// Return an array of Filterered Properties of a Type
/// </summary>
/// <param name="type"></param>
/// <returns>Properties that are filtered by Type</returns>
private static PropertyInfo[] GetFilteredProperties(Type type)
{
return type.GetProperties()
.Where(p => p.Name != "Id" && !p.PropertyType.IsSubclassOf(typeof(BaseEntity)) && !p.PropertyType.IsInterface)
.ToArray();
}
}
公共静态类DataTableExtensions
{
///
///将IEnumerable转换为Datatable
///
///
///
///
公共静态数据表ListToDataTable(此IEnumerable ListToDataTable)
{
DataTable=新的DataTable();
AddToDataTableColumns(dataTable);
foreach(listToDataTable中的变量项)
{
AddDataTableRows(数据表,项);
}
返回数据表;
}
///
///将类的类型转换为DataTable
///
///
///
///
公共静态数据表ToDataTable(此T对象),其中T:class
{
DataTable=新的DataTable();
AddToDataTableColumns(dataTable);
AddDataTableRows(dataTable,obj);
返回数据表;
}
///
///将T类型的值添加到给定的Datatable列
///
///从中提取值
///要向其中添加列值的datatable
///
专用静态DataTable AddToDataTableColumns(DataTable DataTable)
{
尝试
{
PropertyInfo[]FilteredProperties=GetFilteredProperties(类型为(T));
for(int i=0;ip.Name!=“Id”&&&!p.PropertyType.IsSubclassOf(typeof(BaseEntity))&&&!p.PropertyType.IsInterface)
.ToArray();
}
}
否