All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
掌握AJAX之AJAX通讯技术简介_[AJAX教程]
.NET关于同步、异步及Socket_[Asp.Net教程]
GDI+绘制验证码图片
如何利用.NET,Framework使用RSS,feed_.net资料_编程技术
利用HttpRequest登录到某个网站,然后获取网站信息的程序示例_[Asp.Net教程]
.net读取扩展名为xml的资源文件_[Asp.Net教程]
Web.Config配置节加密和解密_[Asp.Net教程]
C#2.0基本语法二_[Asp.Net教程]
asp.net2.0服务器控件之RadioButton控件
,2.0,中快速实现单点登陆_[Asp.Net教程]
Reading number is top 10 pictures
So beauty, will let you spray blood7
29 the belle stars after bath figure4
遇到插队的怎么办?
The real super beauty12
世界五大海盗
人美胸美腿更美1
看到这个手速,决定过年就让我家猫帮我抢红包了。。
A man's favorite things15
牛奶和人奶哪个好?
Is said to be a Chinese female artist fame explicit pictures before2
Download software ranking
C++编程教程第三版
变速齿轮3.26
WebService在.NET中的实战应用教学视频 → 第4集
超级战舰
双旗镇刀客A
徐若瑄成名作“魔鬼天使”
Rio big adventure
The cock of the Grosvenor LTD handsome
Sora aoi 120 minutes
Adobe Flash Player(IE) 10.0.32.18 浏览器专用的FLASH插件
aaa published in(发表于) 2013/12/18 8:05:16 Edit(编辑)
VS2008的Linq,更新数据就那么费劲?_.net资料_编程技术

VS2008的Linq,更新数据就那么费劲?_.net资料_编程技术

VS2008的Linq,更新数据就那么费劲?_.net资料_编程技术-你的首页-uuhomepage.com

  用.Net两年了,也积累了一些知识和经验,觉得应该做出点自己的东西,而并不只是给别人打工。


  所以决定利用最新发布的VS2008(Orcas) Beta2也加入到WEB 2.0的大潮中来,一来是学以所用,二来在实践中掌握最新的技术。


  现在流行在开发阶段给项目起个Code Name,我也来凑凑热闹,就叫Pluto,以纪念不久前被剥夺九大行星资格的我们天蝎座的守护星——冥王星


  平时有自己的工作,只能利用不多的业余时间开发,所以预计(争取)在VS2008正式发布之际,Pluto也能开发完成。


  在这里,我会记录下开发Pluto中的一些事情。


  WEB 2.0的网站少不了数据库、数据访问,也是一切操作之本,而VS 2008中最大的亮点之一Linq也恰巧是做这个的,所以我的开发从Linq、从数据库开始。网上关于Linq的教学铺天盖地,我不准备重复,我只写下我遇到的问题。


  Linq,更新数据怎么就那么费劲?


  Linq的全称是Language Integrated Query ,也就是说Linq是以一个查询语言的方式出现在我们面前的。在查询方面Linq做了不少的优化,我们不用在费尽心思去拼装SQL语句、组装实体等,所有操作在Linq里都是强类型的,我们用C#代码轻松地写出漂亮的SQL语句。


  那么做为一个查询语言,Linq在数据更新方面又是怎么表现的呢?通常来说Linq的更新会以以下的方式出现(绝大部分教程中都是这么写的)


1var ctx = new MyDataContext();
2var user = ctx.Users.Where(u => u.UserId == userId).Single();
3user.UserName = "New User Name";
4ctx.SubmitChanges();


  这些是C#代码,但是背后做了什么呢?Linq会为我们生成类似一下的SQL语句


1--第一步,查询


2SELECT UserId, UserName, FirstName, LastName, CreatTime From User WHERE UserId = @userId
3
4--第二部,更新
5UPDATE User SET UserName = @newUserName
6WHERE UserId = @oldUserId, userName = @oldUserName, FirstName = @oldFirstName, LastName = @oldLastName


  发现了什么?首先Linq会取出所有的字段,在user.UserName = "New User Name"的时候,记录下UserName字段被更新过了,UPDATE时会只更新UserName,但是把之前所有字段的值放在WHERE语句里来做为条件。


  Are you kidding?! 这样的效率实在是太差了吧?!


  抛开效率问题,接下来我们看另外一种更新,有个某个字段记录页面被访问的次数,平时我们会用


1UPDATE POST SET Views = Views + 1 WHERE PostId = @PostId


  但是如果我们写下如下C#代码


1var ctx = MyDataContext();
2var post = ctx.Posts.Where(p => p.PostId = @postId).Single();
3post.Views++
4ctx.SubmitChanges();


  Linq会怎么做呢?和上面一样!取出所有字段,把View加一,用所有字段做为条件(包括Views),更新回去。


  设想一下,这样一个被频繁使用的计数器,两次操作出现SELECT与UPDATE交叉情况的可能性很大,那么后者还能更新成功么?


  微软就是这样解释的,如果在你更新过程中,有其他人更新了这一行,那么这一行也就不是你所需要的那一行了,为了防止这样的冲突,所以把所有字段都放在WHERE语句中,这是by design的。


  你可以通过其他方法进行更新数据,然而在目前版本,这个方法也表现的不怎么样。


  System.Data.Linq.Table有一个Attach方法,带有三个重载,用来直接更新数据的,我们来一个一个的来看看。


Attach(T entity)
1var ctx = new MyDataContext();
2var newUser = new User();
3newUser.UserId = new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");//假设作为参数传进来的
4newUser.UserName = "New User Name";
5ctx.Users.Attach(newUser);
6ctx.SubmitChanges();


  运行完全没有任何效果,SQL Profiler无任何记录。


Attach(T entity, T original)
1var ctx = new MyDataContext();
2var newUser = new User();
3newUser.UserId = new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");//假设作为参数传进来的
4newUser.UserName = "New User Name";
5var user = ctx.User.Where(u => u.UserId = newUser.UserId).Single();
6ctx.Users.Attach(newUser, user);
7ctx.SubmitChanges();


  运行时提示: Cannot add an entity with a key that is already in use.


Attch(T entity, bool asmodified)
1var ctx = new MyDataContext();
2var newUser = new User();
3newUser.UserId = new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");//假设作为参数传进来的
4newUser.UserName = "New User Name";
5ctx.Users.Attach(newUser, true);
6ctx.SubmitChanges();


  运行时提示:An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.


  怎么办?提示中说"declares a version member ",通常来说是指SQL SERVER中TimeStamp类型的字段,在你所需要更新的表中加上一个字段,并标记为TimeStamp就可以了。但是这样做,对于我们来说仍然是个浪费,并且WHERE语句中仍然会出现TimeStamp的限制。


  你还可以通过在字段上设置UpdateCheck.Never属性来避免更新检查,但是如果数据表更新、新增存储过程,需要重新生成dbml的话,你需要手动重新设置一遍。


  Linq甚至没有一个类似Web引用中Update Web Reference的操作来让你方便的在数据表更新后更新dbml,并且在这个版本都不会提供,你所能做的只有删除原来的表,刷新Server Exploer,重新拖拽到dbml的设计视图中,或者,写个脚本,让SQLMETAL来帮你完成这些。


  结论:


  Linq虽然做为一个查询语言出现,但是在数据更新方面也是做了不少工作的,尤其是一些CHECK的工作,但对于写惯SQL的我们来说,还是很不习惯,甚至觉得,这些工作你不替我做才好呢。


  在没有更好解决办法的前提下,在更新操作上,老老实实的写SQL语句或者存储过程应该是个不坏的选择。





添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.