关于Linq To Sql的效率和设计的问题<>
快新年了:先祝大家新年好。很久没征求大家的意见了。现在想征求大家的意义和设计思路。
最近在研究ORM架构。看了很多ORM架构。都不是很满意。不是配置复杂就是速度慢得像老牛样。
但是我还是选择了一款"老牛":Linq To SQL
先说说我的设计思路:改进Linq To SQL原始的:增加,修改,删除,提高效率
官方提供的
新增方式:
修改时:官方需要从DataContext中抓去一个对象然后更新。这样不用说,相率当然有问题了。
效率问题:DataClasses1DataContext 采用对象跟踪问题
批量提交大数据量会越来越慢,到最后一条数据便得最慢
ct.SubmitChanges();最后才轮到它提交.如果不用对象跟踪的话是不能提交的会有异常出现
坚决办法:改进方法
说说我设计时的想法:
更新:通过我改进的代码来看:有朋友可能会有疑问:UpdateWhere 与 Update两个方法有个是多余的。
UpdateWhere(Expression<Func<T, bool>> expression, Expression<Func<T, T>> updater)
表达式:慢。为啥呢:Expression是需要动态分析和编译的。然后取得数据。大家想想有什么办法可以把速度提起来吗?我没想到。但是这方法有优势:可以更新某个对象的部分字段,而且条件也可以动态的。
Update(T model):更新全部字段。但是速度快。
删除:还没想到有什么方式替换表达式,但是至少需要改进的地方是:避开DataContext操作,自己处理
问题点:为什么不用:table.Context.ExecuteCommand(comand, parameters);
我测试过:好像这个也是慢了点点
个人认为:Linq To SQL的查询不需要改进,Linq To Sql 查询做的很不错的。如果大家觉得查询慢的话。
我是这样认为的:查询速度的提升是在于:数据库的优化,SQL语句的优化(注意自己的Linq写法),PC机的配置等等
如果单单说解析与数据库优化的话:可以忽略的。
另外:
1.将我们写好的扩展抽象出来做个类似NH的ITemplateDao的接口。TemplateDao做基础类
2.然后写一个AOP架构我们的Business业务逻辑控制我们的DataContext.目地:处理事务机制,日志处理
3.在调用我们的业务逻辑的时候注入我们的DataContext,在方法调用完毕的时候,回收DataContex并且提交事务
4.注:每个Dao对象需要动态的注入。然后个每个Dao注入DataContext
经测试结果:比较操作30000条数据
1.Ado.net 2.Linq 3.EnterpriseLibrary 4.Linq是否使用表达式
增加耗时: 4.5152583秒 5.8073322秒 13.5097727秒 否
修改耗时: 4.6222644秒 5.4363109秒 18.3780511秒 否
删除耗时: 3.5042004秒 17.2679877秒 6.3913656秒 是
查询耗时: 未测试
问题点:Linq表达式速度没办法提起来,向大家请教如何提高Expression的动态编译。
在网找了个编译缓存的代码,但是还是慢,我的目标是:使用表达式争取接近:Enterprise Library的速度
请大家帮我想想如何提高表达式的编译速度。
最近在研究ORM架构。看了很多ORM架构。都不是很满意。不是配置复杂就是速度慢得像老牛样。
但是我还是选择了一款"老牛":Linq To SQL
先说说我的设计思路:改进Linq To SQL原始的:增加,修改,删除,提高效率
官方提供的
新增方式:
DataClasses1DataContext ct = new DataClasses1DataContext();
for (int i = 0; i < 10000; i++)
{
Common_Gen m = new Common_Gen();
m.GenId = 1;
m.GenType = "Type";
m.Memo = "Memo";
m.UpdateDate = DateTime.Now;
ct.Common_Gen.InsertOnSubmit(m);
}
ct.SubmitChanges();
修改时:官方需要从DataContext中抓去一个对象然后更新。这样不用说,相率当然有问题了。
效率问题:DataClasses1DataContext 采用对象跟踪问题
批量提交大数据量会越来越慢,到最后一条数据便得最慢
ct.SubmitChanges();最后才轮到它提交.如果不用对象跟踪的话是不能提交的会有异常出现
坚决办法:改进方法
/// <summary>
/// 新增数据
/// </summary>
/// <typeparam name="TEntity">实体</typeparam>
/// <param name="table">Table</param>
/// <returns>n</returns>
public static int Add<TEntity>(this Table<TEntity> table, TEntity entity) where TEntity : class
{
DbCommand cmd = table.Context.Connection.CreateCommand();
Type entityType = typeof(TEntity);
var metaTable = table.Context.Mapping.GetTable(entityType);
ReadOnlyCollection<MetaDataMember> dataMembers = metaTable.RowType.DataMembers;
List<object> values = new List<object>();
//自动增长列
string IsDbGeneratedColumnName = null;
StringBuilder sbColumnNames = new StringBuilder();
StringBuilder sbValues = new StringBuilder();
foreach (MetaDataMember mm in dataMembers)
{
if (!mm.IsDbGenerated && mm.DbType != null)
{
sbColumnNames.Append("[" + mm.Name + "],");
sbValues.Append("@" + mm.Name + ",");
DbParameter ps = cmd.CreateParameter();
ps.ParameterName = mm.Name;
ps.Value = entityType.GetProperty(mm.Name).GetValue(entity, null);
cmd.Parameters.Add(ps);
}
if (mm.IsDbGenerated && mm.IsPrimaryKey)
{
IsDbGeneratedColumnName = mm.Name;
}
}
sbColumnNames.Remove(sbColumnNames.Length - 1, 1);
sbValues.Remove(sbValues.Length - 1, 1);
var tableName = "[" + metaTable.TableName + "]";
if (cmd.Connection.State != ConnectionState.Open)
{
cmd.Connection.Open();
}
string CommandText = "";
if (IsDbGeneratedColumnName == null)
{
CommandText = "INSERT INTO " + tableName + "(" + sbColumnNames + ") VALUES(" + sbValues + "); ";
cmd.CommandText = CommandText;
cmd.Transaction = table.Context.Transaction;
int n = cmd.ExecuteNonQuery();
return n;
}
else
{
CommandText = "INSERT INTO " + tableName + "(" + sbColumnNames + ") VALUES(" + sbValues + "); SELECT CONVERT(int,SCOPE_IDENTITY()) AS [value]";
cmd.CommandText = CommandText;
cmd.Transaction = table.Context.Transaction;
object n = cmd.ExecuteScalar();
entityType.GetProperty(IsDbGeneratedColumnName).SetValue(entity, n, null);
return 1;
}
}
//数据访问基类:采用直接提交方式,关闭DataContext对象跟踪
public class TemplateDao<T> : ITemplateDao<T> where T : class
{
public DataContext DataContext { get; set; }
/// <summary>
/// 增加实体
/// </summary>
public virtual void Add(T model)
{
Table<T> table = this.DataContext.GetTable<T>();
table.Add(model);
}
/// <summary>
/// 单表删除数据
/// </summary>
/// <param name="expression">Expression表达式</param>
/// <returns>影响的行数</returns>
public virtual int Delete(Expression<Func<T, bool>> expression)
{
Table<T> table = this.DataContext.GetTable<T>();
return table.Delete(expression);
}
/// <summary>
/// 单表更新数据
/// </summary>
/// <param name="model">实体</param>
public virtual int Update(T model)
{
Table<T> table = this.LoadAll();
return table.Update(model);
}
/// <summary>
/// 单表更新数据
/// </summary>
/// <param name="expression">条件表达式</param>
/// <param name="updater">更新表达式</param>
/// <returns></returns>
public virtual int UpdateWhere(Expression<Func<T, bool>> expression, Expression<Func<T, T>> updater)
{
Table<T> table = this.LoadAll();
return table.UpdateWhere(expression, updater);
}
}
说说我设计时的想法:
更新:通过我改进的代码来看:有朋友可能会有疑问:UpdateWhere 与 Update两个方法有个是多余的。
UpdateWhere(Expression<Func<T, bool>> expression, Expression<Func<T, T>> updater)
表达式:慢。为啥呢:Expression是需要动态分析和编译的。然后取得数据。大家想想有什么办法可以把速度提起来吗?我没想到。但是这方法有优势:可以更新某个对象的部分字段,而且条件也可以动态的。
Update(T model):更新全部字段。但是速度快。
删除:还没想到有什么方式替换表达式,但是至少需要改进的地方是:避开DataContext操作,自己处理
/// <summary>
/// 单表删除数据
/// </summary>
public static int Delete<TEntity>(this Table<TEntity> table, Expression<Func<TEntity, bool>> filter) where TEntity : class
{
DbCommand cmd = table.Context.Connection.CreateCommand();
//获取表名
string tableName = table.Context.Mapping.GetTable(typeof(TEntity)).TableName;
//查询条件表达式转换成SQL的条件语句
ConditionBuilder builder = new ConditionBuilder();
builder.Build(filter.Body);
string sqlCondition = builder.Condition;
//SQL命令
string commandText = string.Format("DELETE FROM {0} WHERE {1}", tableName, sqlCondition);
cmd.CommandText = commandText;
//获取SQL参数数组
List<KeyValuePair<string, object>> args = builder.Arguments;
foreach (KeyValuePair<string, object> arg in args)
{
DbParameter ps = cmd.CreateParameter();
ps.ParameterName = arg.Key;
ps.Value = arg.Value;
cmd.Parameters.Add(ps);
}
if (table.Context.Connection.State != ConnectionState.Open)
{
table.Context.Connection.Open();
}
if (table.Context.Transaction != null)
{
cmd.Transaction = table.Context.Transaction;
}
return cmd.ExecuteNonQuery();
}问题点:为什么不用:table.Context.ExecuteCommand(comand, parameters);
我测试过:好像这个也是慢了点点
个人认为:Linq To SQL的查询不需要改进,Linq To Sql 查询做的很不错的。如果大家觉得查询慢的话。
我是这样认为的:查询速度的提升是在于:数据库的优化,SQL语句的优化(注意自己的Linq写法),PC机的配置等等
如果单单说解析与数据库优化的话:可以忽略的。
另外:
1.将我们写好的扩展抽象出来做个类似NH的ITemplateDao的接口。TemplateDao做基础类
2.然后写一个AOP架构我们的Business业务逻辑控制我们的DataContext.目地:处理事务机制,日志处理
3.在调用我们的业务逻辑的时候注入我们的DataContext,在方法调用完毕的时候,回收DataContex并且提交事务
4.注:每个Dao对象需要动态的注入。然后个每个Dao注入DataContext
经测试结果:比较操作30000条数据
1.Ado.net 2.Linq 3.EnterpriseLibrary 4.Linq是否使用表达式
增加耗时: 4.5152583秒 5.8073322秒 13.5097727秒 否
修改耗时: 4.6222644秒 5.4363109秒 18.3780511秒 否
删除耗时: 3.5042004秒 17.2679877秒 6.3913656秒 是
查询耗时: 未测试
问题点:Linq表达式速度没办法提起来,向大家请教如何提高Expression的动态编译。
在网找了个编译缓存的代码,但是还是慢,我的目标是:使用表达式争取接近:Enterprise Library的速度
请大家帮我想想如何提高表达式的编译速度。
...全文
相关推荐
LINQ教程中文版(LINQ TO SQL ,LINQ TO XML)
本教程主要涵盖了两个核心部分:LINQ to SQL 和 LINQ to XML,都是针对不同类型数据源进行查询的工具。
深入理解Linq:从Linq To Sql到Linq To DataSet
Linq(Language Integrated Query)是一种在.NET环境中集成查询功能的方式。它提供了一种类型安全、编译时检查的方法来操作数据源中的数据。Linq定义了一系列标准查询操作符,这些操作符可用于查询数组、数据库以及其他数据源。ORM(对象关系映射)框架是现代数据访问技术的核心,它将对象模型映射到关系数据库模型。Linq To Sql作为.NET平台下的ORM框架,简化了数据访问层的开发过程,允许开发者使用C#等.NET语言进行数据库查询,而无需编写传统的SQL语句。
Linq 大全 Linq To Sql Linq To DataSet Linq To Object Linq to Xml
在标题和描述中提到的"Linq To Sql"、"Linq To DataSet"、"Linq To Object"和"Linq To Xml"是LINQ的四种主要应用方式,分别用于SQL数据库、DataSet
linq to sql 、linq to xml 、linq to object
在.NET环境中,LINQ主要分为三个主要部分:LINQ to SQL、LINQ to XML和LINQ to Objects。1.
linq基础 linq to sql
性能优化:虽然LINQ to SQL简化了数据库操作,但在处理大量数据时,应考虑查询效率,避免无效的N+1查询和过度复杂的查询。


LINQ
