最近要优化数据库访问,数据库是SQLSERVER。
对单条数据的插入和更新,之前的做法是先查询数据库是否有记录,有就更新,没有就插入。
查了网上的资料后,别人有个好的做法是直接update,若受影响条数是0就直接插入。不知道有没有更好的。
对与操作历史表的请求,准备做成批量插入。通过使用SqlBulkCopy来批量插入。因为采用了ORM所以批量插入的时候要转model为datatable。所以根据model写了个modelTodatatable的方法来生成datatable对象。
public static DataTable ConvertToDataTable(List<T> models,string TableName)
{
if (models != null && models.Count > 0)
{
DataTable dt = string.IsNullOrEmpty(TableName) ? new DataTable(typeof(T).Name) : new DataTable(TableName);
GetTableColumn(dt,models[0]);
foreach (var m in models)
{
DataRow dr = dt.NewRow();
foreach (var v in typeof(T).GetProperties())
{
if (v.PropertyType.IsValueType || v.PropertyType.Name.StartsWith("String") || v.PropertyType.IsArray)
dr[v.Name] = v.GetValue(m, null);
else
{
object value = v.GetValue(m, null);
foreach (var item in value.GetType().GetProperties())
{
dr[item.Name] = item.GetValue(value, null);
}
}
}
dt.Rows.Add(dr);
}
return dt;
}
else
return null;
}
private static void GetTableColumn(DataTable dt, T model)
{
foreach (var v in typeof(T).GetProperties())
{
if (!v.PropertyType.IsClass || v.PropertyType.Name.StartsWith("String") || v.PropertyType.Name.Contains("[]"))
dt.Columns.Add(v.Name, v.PropertyType);
else
{
object value = v.GetValue(model, null);
foreach (var item in value.GetType().GetProperties())
dt.Columns.Add(item.Name, item.PropertyType);
}
}
}
之前对sqlbulkcopy不了解,对应的数据库表主键是自增列,同时还有image类型,在写代码的时候遇到一些问题,现在把sqlbulkcopy的测试例子贴出来,希望对同样的新人有帮助。
static void Main(string[] args)
{
SqlConnectionStringBuilder sqlstr = new SqlConnectionStringBuilder();
sqlstr.DataSource = "WINDOWS-B7K4U6P\\SQLSERVER2012";
sqlstr.InitialCatalog = "BULKCOPY";
sqlstr.IntegratedSecurity = true;
string conn = sqlstr.ConnectionString;
DataTable dt = new DataTable("Person");
dt.Columns.Add("Name");
dt.Columns.Add("qq");
dt.Columns.Add("Address");
dt.Columns.Add("Pic",typeof(byte[]));
object[] row = { "wxk", "ccccc","cccccc",new byte[]{0xAD,0x24}};
object[] row1 = { "ddd", "ddddd", "ddddd", new byte[] { 0xAD, 0xAA } };
dt.Rows.Add(row);
dt.Rows.Add(row1);
using (SqlBulkCopy sbc = new SqlBulkCopy(conn))
{
sbc.DestinationTableName = "Person";
sbc.ColumnMappings.Add("qq", "QQ");
sbc.ColumnMappings.Add("Pic", "picture");
sbc.ColumnMappings.Add("Name", "Name");
sbc.ColumnMappings.Add("Address", "Address");
sbc.WriteToServer(dt);
}
}
在sqlbulkCopy中只要把model的属性名和数据库的字段名映射好就行,别漏掉了一个,否则就会报错。
对应的数据库表信息:
CREATE TABLE [dbo].[Person](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nchar](10) NULL,
[Address] [nchar](10) NULL,
[PhoneNum] [int] NULL,
[QQ] [nchar](10) NULL,
[picture] [image] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]