详解LINQ to SQL简单的单表批量删除

开发 后端
本文将介绍的是LINQ to SQL简单的单表批量删除,包括操作表达式树操作二元表达式等方面的内容。

今天在网上看到老赵前辈的扩展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呢,我用了正则表达式匹配。就得到了下面完全代码:

  1. public static class TableExtension  
  2.     {  
  3.         /// <summary>  
  4.         /// 单表操作批量删除  
  5.         /// </summary>  
  6.         /// <typeparam name="T"></typeparam>  
  7.         /// <param name="source"></param>  
  8.         /// <param name="query"></param>  
  9.         /// <returns></returns>  
  10. public static int Delete<T>(this System.Data.Linq.Table<T> source, Expression<Func<T, bool>> query)  
  11.             where T : class 
  12.         {  
  13.             if (source == null)  
  14.                 throw new ArgumentException("source");  
  15.             if (query == null)  
  16.                 throw new ArgumentException("query");  
  17.             //query = t => true;  
  18.             //为空DELETE  FROM [dbo].[test] 全删除;个人觉得为空全删除,很不人道,所以还是抛异常  
  19.             System.Data.Linq.DataContext db = source.Context;  
  20.             IQueryable q = source.Where(query).AsQueryable();  
  21.             DbCommand cmd = db.GetCommand(q);  
  22.             string sql = cmd.CommandText;  
  23.             string regex =  
  24.  @"from\s*\[\s*dbo\s*\]\s*\.\s*\[\s*\w+\s*\]\s*(?<tableparam>(as\s*(?<tablepname>(\[\s*\w+\s*\]))))(\.|(\r)|(\n))*";  
  25. MatchCollection matches = Regex.Matches(sql, regex, RegexOptions.Multiline | RegexOptions.IgnoreCase);  
  26.             Debug.Assert(matches != null"regex match :null");  
  27.             Debug.Assert(matches.Count == 1, "regex match length :" + matches.Count);  
  28.             if (matches != null && matches.Count > 0)  
  29.             {  
  30.                 Match match = matches[0];  
  31.  sql = ("DELETE  " + match.Value.Replace(match.Groups["tableparam"].Value, "") +  
  32.     sql.Substring(match.Index + match.Length)).Replace(match.Groups["tablepname"].Value + "."" ");  
  33.    List<object> dbparams = new List<object>();  
  34. foreach (SqlParameter item in cmd.Parameters)  
  35.                 {  
  36.    SqlParameter p = new SqlParameter(item.ParameterName, item.SqlDbType, item.Size);  
  37.                     p.Value = item.Value;  
  38.                     dbparams.Add(item.Value);  
  39.                 }  
  40.                 q = null;  
  41.                 cmd = null;  
  42.                 matches = null;  
  43.     Debug.WriteLine("delete sql :" + sql);  
  44.    return db.ExecuteCommand(sql, dbparams.ToArray());  
  45.  
  46.  
  47.             }  
  48.             return 0;  
  49.         } 

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

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

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

image

在看一个:

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

image

这个扩展中的缺点:

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也完全可以实现,就几行代码而已。

还想多写一些优点,暂时就想到这些,有什么Bug或者建议请大家一定要指出。还有就是不知道这样对内存有么有影响,还没有来得及测试。我个人觉得其实计算机的东西都是我们生活中简单的问题运用,就在个人的思维了,就和前面讲的老外Linq组合查询的PredicateExtensions类一样。恩现在赶紧去看看老赵前辈的实现方式了,还没来得及看过一行代码呢,不知对事务、多表的支持如何。

[[13908]]

原文标题:Linq To Sql 简单的单表批量删除

链接:http://www.cnblogs.com/whitewolf/archive/2010/08/04/1791682.html

【编辑推荐】

  1. Linq匿名类型简单概述
  2. Linq随机读取数据浅析
  3. Linq Lambda表达式全面分析
  4. Linq扩展方法简单分析
  5. 初探Linq局部变量类型

 

责任编辑:彭凡 来源: 博客园
相关推荐

2009-09-14 13:17:51

LINQ to SQLLINQ to SQL

2010-09-02 10:53:21

SQL删除

2009-09-11 09:41:19

LINQ to SQL

2009-09-08 13:16:01

Linq to SQL

2009-09-18 14:51:19

LINQ TO SQL

2010-09-03 11:52:41

SQL删除

2009-09-14 09:46:00

LINQ to SQL

2009-09-15 13:37:24

Linq To Sql

2009-09-15 13:53:53

Linq To Sql

2010-07-09 15:31:25

SQL Server

2010-09-01 15:30:24

SQL删除

2009-09-14 10:12:11

LINQ to SQL

2009-09-17 15:51:39

Linq to sql

2010-09-03 11:47:38

SQL删除

2010-09-01 16:26:11

SQL删除批量

2009-09-07 16:13:14

LINQ to SQL

2009-09-09 11:24:13

Linq使用数据表

2009-04-20 15:54:04

SQL Server重复行

2009-09-15 15:45:00

Linq联合查询

2009-09-14 19:20:22

LINQ TO SQL
点赞
收藏

51CTO技术栈公众号