当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > Linq to SQL Delete时遇到问题的解决方法

ASP.NET
asp.net Execl的添加,更新操作实现代码
asp.net 生成曲线图实现代码
从外部的js文件中获取ASPX页面的控件ClientID
asp.net 因为数据库正在使用的解决方法
asp.net Repeater 自递增
asp.net 实现防迅雷等下载工具盗链
ASP.NET封装的SQL数据库访问类
asp.net 通过指定IP地址得到当前的网络上的主机的域名
aspx 服务器架设问题解决
ASP.NET Session使用详解
Asp.net 5种页面转向方法
ASP.NET 用户多次登录的解决方法
ASP.NET下母版页和内容页中的事件发生顺序整理
asp.net 程序性能优化的七个方面 (c#(或vb.net)程序改进)
从客户端检测到有潜在危险的Request.Form值的asp.net代码
asp.net CommunityServer中的wwwStatus
在应用程序级别之外使用注册为allowDefinition=''MachineToApplication''的节是错误的
.net开发人员常犯的错误分析小结
ASP.net Substitution 页面缓存而部分不缓存的实现方法
asp.net 生成静态时的过滤viewstate的实现方法

ASP.NET 中的 Linq to SQL Delete时遇到问题的解决方法


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-11   浏览: 158 ::
收藏到网摘: n/a

在Linq to SQL中要删除一行记录,官方的例子教我这样做

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)

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