Linq to SQL笔记(二)
今天用Linq给数据表批量添加数据时,发现速度确实比ADO.net慢了不少,后面调出DataContext.Log记录一看,发现是一行一个命令添加数据,那速度当然慢了了,差不多慢了20倍左右,Linq的本质就是通过映射类等把c#等.net语言解释为SQL语句,我按照这个思路自己把程序语言解释为SQL,听说可以使用System.Linq.Expression里面的方法解释成SQL语句,但是我看了网上的代码,看不太明白,我就按自己想法封装了一个Insert方法,速度接近ADO.net有不对的请指正。
第一步:从数据表映射类解释出表名,表列。
先建立一个数据表映射类:
View Code
1 [Table(Name = "Student")]
2 public class Student
3 {
4 [Column(Name = "序号", CanBeNull = false, IsPrimaryKey = true)]
5 public int ID { get; set; }
6 [Column(Name = "名字", CanBeNull = false)]
7 public string Name { get; set; }
8 [Column(Name = "年龄", CanBeNull = false)]
9 public int Age { get; set; }
10
11 public Student() { }
12
13 public Student(int id, string name, int age)
14 {
15 ID = id;
16 Name = name;
17 Age = age;
18 }
19
20 public override string ToString()
21 {
22 return ID.ToString() + "\t" + Name + "\t" + Age.ToString();
23 }
24 }
1、获取表名
View Code
1 public static class DataContextExtension
2 {
3 private static string GetTableName<TEntity>(this DataContext context)
4 {
5 string tableName = "";
6 Attribute[] atb = Attribute.GetCustomAttributes(typeof(TEntity));
7 foreach (var item in atb)
8 {
9 if (item.GetType() == typeof(TableAttribute))
10 {
11 tableName = ((TableAttribute)item).Name;
12 }
13 }
14 return tableName;
15 }
16 }
2、获取列名及相关属性
View Code
1 public static Dictionary<PropertyInfo,ColumnAttribute> GetTableCol<TEntity>(this DataContext context)
2 {
3 Dictionary<PropertyInfo,ColumnAttribute> col = new Dictionary<PropertyInfo,ColumnAttribute>();
4
5 PropertyInfo[] m = typeof(TEntity).GetProperties();
6 foreach (var item in m)
7 {
8 Attribute[] pat = Attribute.GetCustomAttributes(item);
9 foreach (var item1 in pat)
10 {
11 if (item1.GetType() == typeof(ColumnAttribute))
12 {
13 col[item] = (ColumnAttribute)item1;
14 }
15 }
16 }
17 return col;
18 }
第二步、把数据解释并生成SQL Insert语句
1、创建Insert SQL语句
View Code
1 public static string CreateInsertCmd<TEntity>(this DataContext context, IEnumerable<TEntity> collection,int TEntityLength = 50)
2 {
3 StringBuilder cmd = new StringBuilder(collection.Count<TEntity>() *TEntityLength + 100);
4 //获取表名
5 string tableName = GetTableName<TEntity>(context);
6 //获取表列
7 Dictionary<PropertyInfo,ColumnAttribute> col = GetTableCol<TEntity>(context);
8 string insert = "insert into " + tableName + "(";
9 foreach (var item in col)
10 {
11 if (!item.Value.IsDbGenerated)
12 {
13 insert += "["+item.Value.Name + "],";
14 }
15 }
16 cmd.Append(insert);
17 cmd.Remove(cmd.Length - 1, 1);
18 cmd.Append(") values");
19 //添加数据
20 foreach (var item in collection)
21 {
22 cmd.Append("(");
23 foreach (var c in col)
24 {
25 if (!c.Value.IsDbGenerated)
26 {
27 if (c.Key.PropertyType == typeof(string))
28 {
29 cmd.Append("'" + c.Key.GetValue(item, null).ToString() + "',");
30
31 }
32 else
33 {
34 cmd.Append(c.Key.GetValue(item, null).ToString() + ",");
35 }
36 }
37 }
38 cmd.Remove(cmd.Length - 1, 1);
39 cmd.Append("),");
40
41 }
42 cmd.Remove(cmd.Length - 1, 1);
43 cmd.Append(";");
44
45 return cmd.ToString();
46 }
2、当批量数据大于1000行时,需把Insert语句拆分为不大于1000行的多个Insert语句
View Code
1 public static string[]CreateInsertCmds<TEntity>(this DataContext context, IEnumerable<TEntity> collection,int TEntityLength = 50)
2 {
3 int n = 998;
4 int cmdCount = collection.Count<TEntity>() / n;
5 string[] cmds = new string[cmdCount+1];
6 List<TEntity> l = collection.ToList<TEntity>();
7 int i;
8 for (i = 0; i < cmdCount ; i++)
9 {
10 cmds[i] = CreateInsertCmd<TEntity>(context,l.GetRange(i*n,n));
11 }
12 cmds[i] = CreateInsertCmd(context,l.GetRange(i*n,collection.Count<TEntity>() - i*n));
13 return cmds;
14 }
第三步,执行DataContext.ExecuteCommand
View Code
1 public static void InsertAll<TEntity>(this DataContext context,IEnumerable<TEntity>collection)
2 {
3 string []cmds = CreateInsertCmds<TEntity>(context,collection);
4 foreach (var item in cmds)
5 {
6 context.ExecuteCommand(item);
7 }
8 }
第三步,完整代码及测试代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq.Mapping;
using System.Data.Sql;
using System.Reflection;
#if DEBUG
using System.Diagnostics;
using NUnit.Framework;
#endif
namespace System.Data.Linq
{
public static class DataContextExtension
{
public static bool CreateTable(this DataContext context, Type type)
{
MetaTable metaTable = context.Mapping.GetTable(type);
string typeName = "System.Data.Linq.SqlClient.SqlBuilder";
Type contextType = typeof(DataContext).Assembly.GetType(typeName);
if (contextType == null)
{
return false;
}
BindingFlags bf = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod;
object sql = contextType.InvokeMember("GetCreateTableCommand", bf, null, null, new[] { metaTable });
if (context.ExecuteCommand((string)sql, new object[] { }) <= 0)
{
return false;
}
return true;
}
public static bool CreateTable<TEntity>(this DataContext context)
{
return CreateTable(context, typeof(TEntity));
}
public static bool DeleteTable(this DataContext context, Type type)
{
MetaTable metaTable = context.Mapping.GetTable(type);
string cmdtext = "drop table "+metaTable.TableName;
if (context.ExecuteCommand(cmdtext, new object[] { }) > 0)
{
return true;
}
else
{
return false;
}
}
public static bool DeleteTable<TEntity>(this DataContext context)
{
return DeleteTable(context, typeof(TEntity));
}
public static string[]CreateInsertCmds<TEntity>(this DataContext context, IEnumerable<TEntity> collection,int TEntityLength = 50)
{
int n = 998;
int cmdCount = collection.Count<TEntity>() / n;
string[] cmds = new string[cmdCount+1];
List<TEntity> l = collection.ToList<TEntity>();
int i;
for (i = 0; i < cmdCount ; i++)
{
cmds[i] = CreateInsertCmd<TEntity>(context,l.GetRange(i*n,n));
}
cmds[i] = CreateInsertCmd(context,l.GetRange(i*n,collection.Count<TEntity>() - i*n));
return cmds;
}
public static void InsertAll<TEntity>(this DataContext context,IEnumerable<TEntity>collection)
{
string []cmds = CreateInsertCmds<TEntity>(context,collection);
foreach (var item in cmds)
{
context.ExecuteCommand(item);
}
}
public static string CreateInsertCmd<TEntity>(this DataContext context, IEnumerable<TEntity> collection,int TEntityLength = 50)
{
StringBuilder cmd = new StringBuilder(collection.Count<TEntity>() *TEntityLength + 100);
//获取表名
string tableName = GetTableName<TEntity>(context);
//获取表列
Dictionary<PropertyInfo,ColumnAttribute> col = GetTableCol<TEntity>(context);
string insert = "insert into " + tableName + "(";
foreach (var item in col)
{
if (!item.Value.IsDbGenerated)
{
insert += "["+item.Value.Name + "],";
}
}
cmd.Append(insert);
cmd.Remove(cmd.Length - 1, 1);
cmd.Append(") values");
//添加数据
foreach (var item in collection)
{
cmd.Append("(");
foreach (var c in col)
{
if (!c.Value.IsDbGenerated)
{
if (c.Key.PropertyType == typeof(string))
{
cmd.Append("'" + c.Key.GetValue(item, null).ToString() + "',");
}
else
{
cmd.Append(c.Key.GetValue(item, null).ToString() + ",");
}
}
}
cmd.Remove(cmd.Length - 1, 1);
cmd.Append("),");
}
cmd.Remove(cmd.Length - 1, 1);
cmd.Append(";");
return cmd.ToString();
}
public static Dictionary<PropertyInfo, ColumnAttribute> GetTableCol<TEntity>(this DataContext context)
{
Dictionary<PropertyInfo, ColumnAttribute> col = new Dictionary<PropertyInfo, ColumnAttribute>();
PropertyInfo[] m = typeof(TEntity).GetProperties();
foreach (var item in m)
{
Attribute[] pat = Attribute.GetCustomAttributes(item);
foreach (var item1 in pat)
{
if (item1.GetType() == typeof(ColumnAttribute))
{
col[item] = (ColumnAttribute)item1;
}
}
}
return col;
}
private static string GetTableName<TEntity>(this DataContext context)
{
string tableName = "";
Attribute[] atb = Attribute.GetCustomAttributes(typeof(TEntity));
foreach (var item in atb)
{
if (item.GetType() == typeof(TableAttribute))
{
tableName = ((TableAttribute)item).Name;
}
}
return tableName;
}
}
[Table(Name = "Teacher")]
public class Teacher
{
[Column(Name = "序号",IsPrimaryKey = true, CanBeNull = false)]
public int ID { get; set; }
[Column(Name = "名字",CanBeNull = false)]
public string Name { get; set; }
[Column(Name = "年龄",CanBeNull = false)]
public int Age { get; set; }
}
public class Person : DataContext
{
public Table<Student> Student;
public Person(string conString)
: base(conString)
{
}
}
#if DEBUG
[TestFixture]
public class LinqSql
{
public static string constr = AppDomain.CurrentDomain.BaseDirectory + @"\Person1.mdf";
public static Person db;
[Test]
public static void CreateDatabase()
{
db = new Person(constr);
if (db.DatabaseExists())
{
db.DeleteDatabase();
db.Connection.Close();
db.Dispose();
db = new Person(constr);
}
db.CreateDatabase();
Trace.WriteLine(constr);
Trace.WriteLine(constr);
db.CreateTable(typeof(Teacher));
Table<Teacher> tl;
if ((tl =db.GetTable<Teacher>()) != null)
{
Trace.WriteLine(typeof(Teacher) + "表已经存在");
db.DeleteTable<Teacher>();
}
}
[Test]
public static void CreateInsertCmd()
{
List<Teacher> tl = new List<Teacher>() { new Teacher() { Name = "fds", ID = 1, Age = 22 } ,
new Teacher(){Name = "ffdf",ID = 2,Age = 23}};
db.InsertAll<Teacher>(tl);
}
}
#endif
}

浙公网安备 33010602011771号