惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
V
V2EX
B
Blog RSS Feed
有赞技术团队
有赞技术团队
博客园 - Franky
美团技术团队
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
云风的 BLOG
云风的 BLOG
L
LangChain Blog
GbyAI
GbyAI
The Cloudflare Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Stack Overflow Blog
Stack Overflow Blog
博客园 - 【当耐特】
The Register - Security
The Register - Security
大猫的无限游戏
大猫的无限游戏
D
Docker
Vercel News
Vercel News
Blog — PlanetScale
Blog — PlanetScale
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 司徒正美
人人都是产品经理
人人都是产品经理
雷峰网
雷峰网
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
N
Netflix TechBlog - Medium
博客园_首页
A
About on SuperTechFans
J
Java Code Geeks
量子位
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
MongoDB | Blog
MongoDB | Blog
Recent Announcements
Recent Announcements
G
Google Developers Blog
小众软件
小众软件
博客园 - 叶小钗
WordPress大学
WordPress大学
博客园 - 聂微东
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Martin Fowler
Martin Fowler
S
SegmentFault 最新的问题
F
Full Disclosure
Jina AI
Jina AI
H
Help Net Security

博客园 - J. Lin

据可靠小道消息VS 2008 SP1 RTM 将在下周一发布 Configuration Section Designer 自定义配置设计器 [CSS Hack] border-color:transparent & filter+ClearType bug ASP.NET AJAX 1.0 & AJAX Control Toolkit 在iframe中的"access denied"错误 Aptana使用入门一:Code Assist What we can do in "Page" class 页面基类功能扩展汇总 不可多得的Javascript(AJAX)开发工具 - Aptana 右键菜单快速打开VS 2005 Website项目 SQL Server 2005 SP1 安装问题 设置asp.net程序在web.config被修改后是否重启 VS2005 Add-in:CSS Properties Window 在MastPage中引用脚本资源 Design Templates for ASP.NET 2.0 Security Guidelines: ASP.NET 2.0 [目录] & [How to列表] ASP.NET 2.0 Security FAQs 翻译计划 [ASP.NET 2.0 Security FAQs]如何在membership中强制使用高安全性的密码 [ASP.NET 2.0 Security FAQs]如何设置SQL Server或SQL Express数据库,使其支持Membership、Profiles和Role Web.config 文件中的“智能感知” 用宏自动生成Web.sitemap文件(ASP.NET 2.0)
Linq to Sql: 批量删除之投机取巧版
J. Lin · 2008-03-07 · via 博客园 - J. Lin

前些天看了Jeffrey扩展LINQ to SQL:使用Lambda Expression批量删除数据。说实话解析表达式生成Where Condition的那部分代码基本没看懂(事实是代码太多实在是没耐心看)。

根据Linq to Sql原有的设计,解析Query得到DbCommand应该是SqlProvider干的事,只是现在这个SqlProvider只从IReaderProvider出(事实上MS也没设计个IUpdateProvider或者IDeleteProvider来着),所以也只对SELECT感冒。搞的咱们只能在DataContext里自力更生了。

不过既然已经有了可以生成SELECT的IReaderProvider,稍微把SELECT语句改造一下不就能得到DELETE了吗!基本思路:

        public static int DeleteAll<TEntity>(this Table<TEntity> table, Expression<Func<TEntity, bool>> predicate)
           
where TEntity : class
       
{
           
IQueryable query = table.Where(predicate);
           
DbCommand com = dc.GetCommand(query);

            //TODO:改造sql语句

            return com.ExecuteNonQuery();
         }
    }

这里直接拿直接拿where生成的query来GetCommand,得到的sql语句大致如下:

SELECT fields... FROM tableName AS TableAlias WHERE Condition

我们的目标是改造成:

DELETE FROM tableName WHERE Condition

可见关键是得到tableName,用正则是首选。不过这里还有一个缺陷就是只能用expression来做删除不能用linq query,比如我想这样:

            var query = from item in context.Items
                       
where item.Name.StartsWith("XX")
                       
select item;
            context.DeleteAll(query);

看来要把DeleteAll放到DataContext里,不过这样有风险,有可能会接受到无法转换的SELECT语句,增加判断必不可少。

最终完成如下:

    public static class DataContextEx
    {
        public static int DeleteAll(this DataContext dc, IQueryable query)
        {
            DbCommand com = dc.GetCommand(query);

            Regex reg = new Regex("^SELECT[\\s]*(?<Fields>.*)[\\s]*FROM[\\s]*(?<Table>.*)[\\s]*AS[\\s]*(?<TableAlias>.*)[\\s]*WHERE[\\s]*(?<Condition>.*)",
                                    RegexOptions.IgnoreCase);

            Match match = reg.Match(com.CommandText);

            if (!match.Success)
                throw new ArgumentException("Cannot delete this type of collection");

            string table = match.Groups["Table"].Value.Trim();
            string tableAlias = match.Groups["TableAlias"].Value.Trim();
            string condition = match.Groups["Condition"].Value.Trim().Replace(tableAlias, table);

            com.CommandText = string.Format("DELETE FROM {0} WHERE {1}", table, condition);

            if (com.Connection.State != System.Data.ConnectionState.Open)
                com.Connection.Open();

            return com.ExecuteNonQuery();
        }


        public static int DeleteAll<TEntity>(this Table<TEntity> table, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            IQueryable query = table.Where(predicate);

            return table.Context.DeleteAll(query);
        }
    }

注:reg表达式取自MSDN Forum