广

ASP.NET

  • IOS开发
  • android开发
  • PHP编程
  • JavaScript
  • ASP.NET
  • ASP编程
  • JSP编程
  • Java编程
  • 易语言
  • Ruby编程
  • Perl编程
  • AJAX
  • 正则表达式
  • C语言
  • 编程开发

    Linq to SQL Delete时遇到问题的解决方法

    2018-05-04 21:21:01 次阅读 稿源:互联网
    广告

    1.1、

    Code1:
    using (PubsDataContext pubsContent = new PubsDataContext())
    {
        pubsContent.Log = Console.Out;
        Author author = pubsContent.Authors.Single(a => a.au_id == "111-11-1111");
        pubsContent.Authors.DeleteOnSubmit(author);
        pubsContent.SubmitChanges();
    }

    可是,马上我的程序支持到这里就跑不动了,第二行有异常。

    image

    为什么呢?

    看一下MSDN关于Signle方法的说明:

    image

    哦,问题出在这里,Single要求符合条件的记录有且只有一行,否则就会发飙。

    从以前的学习中我知道,调用Single方法时DataContent即刻从数据库中获取数据库,而这个时间如果获取不到auid="111-11-1111"的记录,返回的记录集是空的,就引发了上面的异常。

    1.2、

    我想找一个方法,让Linq不执行Select而直接Delete,搜完了MSDN,翻完了《LINQ in Action》,没有。

    后来我想,既然Linq to sql有“延迟加载”功能,那么删除时能不能也“延迟”呢,我尝试这样:

    Code 2:
    using (PubsDataContext pubsContent = new PubsDataContext())
    {
        var q = from a in pubsContent.Authors
                where a.au_id == "111-11-1111"
                select a;
        pubsContent.Log = Console.Out;
        pubsContent.Authors.DeleteAllOnSubmit(q);
        pubsContent.SubmitChanges();
    }

    我的程序被驯服了,不在这里发飙了。

    难道Linq to sql真如我所想的直接执行delete from Authors where au_id='111-11-1111'这样的语句了吗?

    2.1

    带着上面的疑问,一步一步跟踪查看DataContent的Log。我发现,在用Single()方法来删除的时候,如果不出现异常,提交的SQL语句是这样的。

    image_thumb_2

    这里可以很清楚看出,Linq先从数据库中取出记录,然后再Delete。我们知道主键就可以确定表中唯一的记录了,可是为什么删除条件要把所有的列都加进去呢?老赵在这个post(在Linq to Sql中管理并发更新时的冲突[1],[2],[3] )里很详细的说明了这个问题。

    我的目的只是要删除一行记录,可是这样使用Linq to sql却先从数据库里取出来再删除,实在是多此一举。那Code 2中的方法又是如何运行的呢?我们再来跟踪它。

    2.2

    为了更好的说明问题,我把Code 1中的代码改一下,另外还在数据库中预先添加二行记录,au_id分别为111-11-1111、111-11-1112

    Code 3:
    using (PubsDataContext pubsContent = new PubsDataContext())
    {
        pubsContent.Log = Console.Out;
        var q = from a in pubsContent.Authors
                where a.au_id.StartsWith("111-11-111")
                select a;
        pubsContent.Authors.DeleteAllOnSubmit(q);
        pubsContent.SubmitChanges();
    }

    把==条件换成了StartsWith(生成SQL语句时,StartWith会生成Like '111-11-111%'匹配)。

    现在再下这段代码执行的Log:

    SELECT [t0].[au_id], [t0].[au_lname], [t0].[au_fname], [t0].[phone],
    [t0].[address], [t0].[city], [t0].[state], [t0].[zip], [t0].[contract]
    FROM [dbo].[authors] AS [t0]
    WHERE [t0].[au_id] LIKE @p0
    -- @p0: Input VarChar (Size = 11; Prec = 0; Scale = 0) [111-11-111%]
    -- Context: SqlProvider(Sql2000) Model: AttributedMetaModel Build: 3.5.21022.8
     
    DELETE FROM [dbo].[authors] WHERE ([au_id] = @p0) AND ([au_lname] = @p1)
    AND ([au_fname] = @p2) AND ([phone] = @p3) AND ([address] = @p4)
    AND ([city] = @p5) AND ([state] = @p6) AND ([zip] = @p7) AND ([contract] = 1)
    -- @p0: Input VarChar (Size = 11; Prec = 0; Scale = 0) [111-11-1111]
    -- @p1: Input VarChar (Size = 3; Prec = 0; Scale = 0) [qqq]
    -- @p2: Input VarChar (Size = 3; Prec = 0; Scale = 0) [qqq]
    -- @p3: Input Char (Size = 12; Prec = 0; Scale = 0) [qqq         ]
    -- @p4: Input VarChar (Size = 3; Prec = 0; Scale = 0) [qqq]
    -- @p5: Input VarChar (Size = 3; Prec = 0; Scale = 0) [qqq]
    -- @p6: Input Char (Size = 2; Prec = 0; Scale = 0) [qq]
    -- @p7: Input Char (Size = 5; Prec = 0; Scale = 0) [22222]
    -- Context: SqlProvider(Sql2000) Model: AttributedMetaModel Build: 3.5.21022.8
     
    DELETE FROM [dbo].[authors] WHERE ([au_id] = @p0) AND ([au_lname] = @p1)
    AND ([au_fname] = @p2) AND ([phone] = @p3) AND ([address] = @p4)
    AND ([city] = @p5) AND ([state] = @p6) AND ([zip] = @p7) AND ([contract] = 1)
    -- @p0: Input VarChar (Size = 11; Prec = 0; Scale = 0) [111-11-1112]
    -- @p1: Input VarChar (Size = 3; Prec = 0; Scale = 0) [qqq]
    -- @p2: Input VarChar (Size = 3; Prec = 0; Scale = 0) [qqq]
    -- @p3: Input Char (Size = 12; Prec = 0; Scale = 0) [qqq         ]
    -- @p4: Input VarChar (Size = 3; Prec = 0; Scale = 0) [qqq]
    -- @p5: Input VarChar (Size = 3; Prec = 0; Scale = 0) [qqq]
    -- @p6: Input Char (Size = 2; Prec = 0; Scale = 0) [qq]
    -- @p7: Input Char (Size = 5; Prec = 0; Scale = 0) [22222]

    很失望,和我期待的结果不一样。

    在这个测试中,DataContent先把所有符合条件的记录全部取回来,再一个一个Delete。

    如果要删除的有10000条记录的话,天都黑了...

    这点,不得不说Linq to sql有点笨了。

    3

    解决?

    只能绕个圈子了。

    DataContext提供有ExecuteCommend方法,可能使用此方法直接执行SQL命令。比如这样:

    Code 4:
    using (PubsDataContext pubsContent = new PubsDataContext())
    {
        pubsContent.Log = Console.Out;
        pubsContent.ExecuteCommand("delete from Authors where au_id like '111-11-111%'");
    }

    也可以通过DataContext.Connection取得当前的数据库连接,然后再通过DBCommend来提交自己的SQL语句,

    或者写个存储过程来负责删除。

    4

    LINQ,语言级集成查询(Language INtegrated Query)

    明显,强在查询,删除就弱弱点 ;-)...

    一起学吧部分文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与一起学吧进行文章共享合作。

    广告
    广告
    广告