彩票走势图

如何轻松实现Linq To Sql 简单的单表批量删除

转帖|其它|编辑:郝浩|2010-12-28 17:07:16.000|阅读 620 次

概述:本文主要介绍如何轻松实现Linq To Sql 简单的单表批量删除,希望对大家有帮助。

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

  今天在网上看到老赵前辈的扩展LINQ to SQL:使用Lambda Expression批量删除数据,我看完了文章,还没有看源代码,我一般都习惯于在看别人的代码前,思考一下如果我来实现我会如何实现。我想了许久操作表达式树操作二元表达式(BinaryExpression)我是肯定困难的,对于表达式类库的了解不多,用了Reflector反射,结果什么都看不见,也许我的Reflector版本低了,没有更新。我就放弃了这种实现方式,我想有没有其他的方式呢?最终我觉得可以操作生成sql执行同样可以达到目的,也许更简单化。

  如何获取sql呢,Linq中有db.GetCommand(IQueryable )方法,DBCommand的CommandText就是sql了,那我们如何获取IQueryable 呢,我的第一感觉就是where方法。所以就有下面的语句了,IQueryable q = source.Where(query).AsQueryable(); DbCommand cmd = db.GetCommand(q);

  现在我们等到了查询sql,如何转化为Delete呢,我用了正则表达式匹配。就得到了下面完全代码:
 

public static class TableExtension
{
/// <summary>
/// 单表操作批量删除
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="query"></param>
/// <returns></returns>
public static int Delete<T>(this System.Data.Linq.Table<T> source, Expression<Func<T, bool>> query)
where T : class
{
if (source == null)
throw new ArgumentException("source");
if (query == null)
throw new ArgumentException("query");
//query = t => true;
//为空DELETE FROM [dbo].[test] 全删除;个人觉得为空全删除,很不人道,所以还是抛异常
System.Data.Linq.DataContext db = source.Context;
IQueryable q = source.Where(query).AsQueryable();
DbCommand cmd = db.GetCommand(q);
string sql = cmd.CommandText;
string regex =
@"from\s*\[\s*dbo\s*\]\s*\.\s*\[\s*\w+\s*\]\s*(?<tableparam>(as\s*(?<tablepname>(\[\s*\w+\s*\]))))(\.|(\r)|(\n))*";
MatchCollection matches = Regex.Matches(sql, regex, RegexOptions.Multiline | RegexOptions.IgnoreCase);
Debug.Assert(matches != null, "regex match :null");
Debug.Assert(matches.Count == 1, "regex match length :" + matches.Count);
if (matches != null && matches.Count > 0)
{
Match match = matches[0];
sql = ("DELETE " + match.Value.Replace(match.Groups["tableparam"].Value, "") +
sql.Substring(match.Index + match.Length)).Replace(match.Groups["tablepname"].Value + ".", " ");
List<object> dbparams = new List<object>();
foreach (SqlParameter item in cmd.Parameters)
{
SqlParameter p = new SqlParameter(item.ParameterName, item.SqlDbType, item.Size);
p.Value = item.Value;
dbparams.Add(item.Value);
}
q = null;
cmd = null;
matches = null;
Debug.WriteLine("delete sql :" + sql);
return db.ExecuteCommand(sql, dbparams.ToArray());

   }
return 0;
}
现在我们可以进行批量删除了,如:

  DataContext.test.Delete(t => t.id > 0 &amp;& t.name.Contains("test") || new string[] { "12", "34", "45" }.Contains(t.name)

  && t.name.Length >1);

  是不是很简单:看看Debug输出的sql:

   

  在看一个:

  DataContext.Orders.Delete(t => !t.EmployeeID1.HasValue);

  这个扩展中的缺点:

   

  1:只针对对单表操作,不支持linq的连接,如:DataContext.test.Delete(t => t.Orders.OrderID > 0);我这个我认为这个可以通过一个更复杂正则表达式完成。还有一种思路更简洁,就是通过sql server支持的表变量或者是临时表先查询出结果,在根据主键实现删除。也许你会说可以写成存储过程,我个人不喜欢它,我一般尽量在程序中TSQL,移植性好,除非性能考虑采用存储过程。

  2:事务处理:在这里只是一个先前的测试Demo,所以么有考虑。我觉得我们可以建立一个类来管理sql语句或者查询条件表达式在调用save方法时候进行内部事务操作(我一般不喜欢将事务显示在外部,因为我觉得事务很费资源,等待时间过长数据库容易崩溃,或者对表的锁定等,不知道这个想法对不对,请大家给个建议)。现在可以在外部事务操作就是有点像ado.net了,呵呵麻烦。

优点:

  1:可以支持复杂的表达式,想老赵提到的"item.Introduction.Length < 10",以及后面评论中提到的in、like等。

  2:实现简单,操作简单,这是最重要的,代码很容易理解。

  3:执行不需要从数据库里取出实体在执行,这是Linq的做法。更符合我们的习惯。我看见在老赵博客最后一个评论说它用EF也实现了批量删除,它的那种方式是取出实体在delete,其实并不是EF特有的,Linq也完全可以实现,就几行代码而已。

   

  

  

  

  

  


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn

文章转载自:网络转载

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP