关于Linq To Sql的效率和设计的问题<>

anzhiqiang_touzi 2011-12-22 11:07:07
快新年了:先祝大家新年好。很久没征求大家的意见了。现在想征求大家的意义和设计思路。
最近在研究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的速度
请大家帮我想想如何提高表达式的编译速度。
...全文
279 3 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
香儿爱土豆 2011-12-31
  • 打赏
  • 举报
回复
没有什么好的~最方便的,最简单的,就是好的~没必要过多纠结于ORM吧,.NET非Java,什么Spring之类的~

.NET4.0之后,你会发现C#越来越爽了,nice~
anzhiqiang_touzi 2011-12-23
  • 打赏
  • 举报
回复
那現在用什麼ORM比較好呢?
vrhero 2011-12-23
  • 打赏
  • 举报
回复
这款老牛早已被淘汰了,没必要在这种过时的过渡产品上浪费任何时间...

8,494

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 LINQ
社区管理员
  • LINQ
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧