开发者社区> 技术小甜> 正文

ADO.NET与ORM的比较(4):EntityFramework实现CRUD

简介:
+关注继续查看
 说明:个人感觉在Java领域大型开发都离不了ORM的身影,所谓的SSH就是Spring+Struts+Hibernate,除了在学习基础知识的时候被告知可以使用JDBC操作数据库之外,大量的书籍中都是讲述使用Hibernate这个ORM工具来操作数据。在.NET中操作数据库的方式有多种,除了最直接的方式就是使用ADO.NET之外,还可以使用NHibernate这个Hibernate在.NET中的实现ORM,如果你对第三方的ORM持怀疑态度,你还可以使用来自微软的实现、根正苗红的Linq或者EntityFramework。
 大部分从早期就开始使用.NET开发的程序员可能对ADO.NET有种迷恋,使用ADO.NET可以充分将我们早期的SQL知识发挥得淋漓尽致,并且出于对性能的考虑,有些人对.NET中的ORM还保持一种观望态度,包括我自己也是这种态度。不过即使在实际开发中不用,并不代表我们不能去了解和比较这些技术,任何事物的出现和消亡总有其原因的,我们可以了解它们的优点和长处。所以本人抽出了几个周末的时间分别用ADO.NET、NHibernate、Linq和EntityFramework来实现对数据库单表数据的创建、读取、更新和删除操作,也就是所谓的CRUD(C:Create/R:Read/U:Update/D:Delete)。
 通过实现相同功能的比较,大家自己判断那种方式更适合自己。需要说明的是,如果在VS2008中使用EntityFramework就需要安装VS2008SP1。
 在本篇讲述的ADO.NET Entity Framework(简称Entity Framework或者干脆称之为EF),在本系列涉及到的几种ORM框架中Entity Framework出现得最晚,在自然界往往遵循着这样一个规律:出现得越晚的生命力越强。特别是编程语言,新出现的语言往往都是为了克服当前主流语言的不足而出现的,就想同样是OOP语言,Java在很多方面就比C++表现优秀,C#又表现得比Java语言一些,这都是因为新的语言都是在借鉴了现有语言的优点并摒弃它们的不足而产生的。在这一点上Entity Framework也是如此。
 一、准备
 向当前项目中添加ADO.NET Entity Framework类,如下图所示:
 
 点击“添加”之后如下图所示:
 
 选择“从数据库生成”,然后点击“下一步”,如下图所示:
 
 如果已经存在数据库连接,就从中选择一个连接,否则就需要新建一个连接。点击“新建连接”之后的界面如下:
 
 这其实就是一个配置数据库连接的界面,填写正确的数据库连接之后点击“确定”按钮,如下图所示:
 
 选择需要的表、视图及存储过程,并填写模型的命名空间,之后点击“完成”,这样就完成了添加ADO.NET Entity Framework模型文件。
 双击刚才添加的模型文件,就可以在设计视图中打开,如下图所示:
 
 我们还可以在设计视图的下方编辑它的属性,如下图所示:
 
 如果以后数据库结构发生了变化,也可以很容易根据数据库来刷新模型文件,如下图所示:
 
 至此,我们完成了初步工作,向当前项目中添加了模型文件。
 二、编码
 和使用Linq to SQL一样,在创建edmx文件时自动创建了相关的实体类代码,因此我们只需根据业务逻辑编写对数据库操作的类即可,代码如下:
InBlock.gifusing System; 
InBlock.gif using System.Collections.Generic; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Text; 
InBlock.gif using System.Data; 
InBlock.gif using System.Data.EntityClient; 
InBlock.gif using System.Configuration; 
InBlock.gif    
InBlock.gif namespace EntityFrameworkDemo 
InBlock.gif { 
InBlock.gif         /// <summary> 
InBlock.gif         /// 说明:这个类是为了演示.NET中的Entity Framework的用法 
InBlock.gif         /// 作者:周公(周金桥) 
InBlock.gif         /// 日期:2010-05-05 
InBlock.gif         /// </summary> 
InBlock.gif         public class EntityFrameworkCRUD 
InBlock.gif         { 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 统计用户总数 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public int Count() 
InBlock.gif                 { 
InBlock.gifInBlock.gif    
InBlock.gif#region 方法二,使用Linq to Entities 
InBlock.gif                         using(AspNetStudyEntities entities = new AspNetStudyEntities()) 
InBlock.gif         { 
InBlock.gif                         //entities.UserInfo.Count<UserInfo>(item => item.Age > 23);//带条件查询 
InBlock.gif                         return entities.UserInfo.Count<UserInfo>(); 
InBlock.gif            } 
InBlock.gif                         #endregion 
InBlock.gif    
InBlock.gif                            
InBlock.gif                 } 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 创建用户 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="info">用户实体</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Create(UserInfo info) 
InBlock.gif                 { 
InBlock.gif                         using(AspNetStudyEntities entities = new AspNetStudyEntities()) 
InBlock.gif         { 
InBlock.gif                         entities.AddToUserInfo(info); 
InBlock.gif                         entities.SaveChanges(); 
InBlock.gif            } 
InBlock.gif                 } 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 读取用户信息 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="userId">用户编号</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public UserInfo Read(int userId) 
InBlock.gif                 { 
InBlock.gif                         //AspNetStudyEntities entities = new AspNetStudyEntities(); 
InBlock.gif                         //return entities.UserInfo.First<UserInfo>(item => item.UserID == userId); 
InBlock.gif    
InBlock.gif方法二,使用EntityKey#region 方法二,使用EntityKey 
InBlock.gif                            using(AspNetStudyEntities entities = new AspNetStudyEntities()) 
InBlock.gif         { 
InBlock.gif                         EntityKey entityKey = new EntityKey("AspNetStudyEntities.UserInfo","UserID",userId); 
InBlock.gif                         return entities.GetObjectByKey(entityKey) as UserInfo; 
InBlock.gif            } 
InBlock.gif                         #endregion 
InBlock.gif                 } 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 更新用户信息 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="info">用户实体</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Update(UserInfo info) 
InBlock.gif                 { 
InBlock.gif                        using(AspNetStudyEntities entities = new AspNetStudyEntities()) 
InBlock.gif         { 
InBlock.gif                         UserInfo ui = entities.UserInfo.First<UserInfo>(item => item.UserID == info.UserID); 
InBlock.gif                         ui.Age = info.Age; 
InBlock.gif                         ui.Email = info.Email; 
InBlock.gif                         ui.Mobile = info.Mobile; 
InBlock.gif                         ui.Phone = info.Phone; 
InBlock.gif                         ui.RealName = info.RealName; 
InBlock.gif                         ui.Sex = info.Sex; 
InBlock.gif                         ui.UserName = info.UserName; 
InBlock.gif                         entities.SaveChanges(); 
InBlock.gif            } 
InBlock.gif                 } 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 删除用户 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="userId">用户编号</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Delete(int userId) 
InBlock.gif                 { 
InBlock.gif#region 方法二 
InBlock.gif                        using(AspNetStudyEntities entities = new AspNetStudyEntities()) 
InBlock.gif         { 
InBlock.gif                         UserInfo ui = entities.UserInfo.First<UserInfo>(item => item.UserID == userId); 
InBlock.gif                         entities.DeleteObject(ui); 
InBlock.gif                         entities.SaveChanges(); 
InBlock.gif            } 
InBlock.gif                         #endregion 
InBlock.gif                 } 
InBlock.gif    
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 删除用户 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="userId">用户实体</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Delete(UserInfo info) 
InBlock.gif                 { 
InBlock.gif                         using(AspNetStudyEntities entities = new AspNetStudyEntities()) 
InBlock.gif         { 
InBlock.gif                         UserInfo ui = entities.UserInfo.First<UserInfo>(item => item.UserID == info.UserID); 
InBlock.gif                         entities.DeleteObject(ui); 
InBlock.gif                         entities.SaveChanges(); 
InBlock.gif            } 
InBlock.gif                 } 
InBlock.gif    
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 获取用户表中编号最大的用户 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public int GetMaxUserId() 
InBlock.gif                 { 
InBlock.gif                         using(AspNetStudyEntities entities = new AspNetStudyEntities()) 
InBlock.gif         { 
InBlock.gif                         int userId=entities.UserInfo.Max<UserInfo>(item => item.UserID); 
InBlock.gif                         return userId; 
InBlock.gif            } 
InBlock.gif                 } 
InBlock.gif         } 
InBlock.gif }

  三、单元测试代码
 为了照顾很多仍在使用NUnit作为单元测试工具的开发人员的习惯,我们的单元测试代码针对NUnit2.5.3,代码如下:
InBlock.gifusing System; 
InBlock.gif using System.Collections.Generic; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Text; 
InBlock.gif using NUnit.Framework; 
InBlock.gif using EntityFrameworkDemo; 
InBlock.gif    
InBlock.gif namespace NUnitTest 
InBlock.gif { 
InBlock.gif         [TestFixture] 
InBlock.gif         class EntityFrameworkTest 
InBlock.gif         { 
InBlock.gif                 private EntityFrameworkCRUD instance = null
InBlock.gif                 [SetUp] 
InBlock.gif                 public void Initialize() 
InBlock.gif                 { 
InBlock.gif                         instance = new EntityFrameworkCRUD(); 
InBlock.gif                 } 
InBlock.gif                 [Test] 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 统计用户总数 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Count() 
InBlock.gif                 { 
InBlock.gif                         Assert.Greater(instance.Count(), 0); 
InBlock.gif                 } 
InBlock.gif                 [Test] 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 创建用户 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="info">用户实体</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Create() 
InBlock.gif                 { 
InBlock.gif                         UserInfo info = new UserInfo() 
InBlock.gif                         { 
InBlock.gif                                 Age=12, 
InBlock.gif                                 Email="zzz@ccav.com"
InBlock.gif                                 Mobile="13812345678"
InBlock.gif                                 Phone="01012345678"
InBlock.gif                                 RealName = "测试" + DateTime.Now.Millisecond.ToString(), 
InBlock.gif                                 Sex=true
InBlock.gif                                 UserName="zhoufoxcn"+DateTime.Now.Millisecond.ToString() 
InBlock.gif                         }; 
InBlock.gif                         instance.Create(info); 
InBlock.gif                 } 
InBlock.gif                 [Test] 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 读取用户信息 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="userId">用户编号</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Read() 
InBlock.gif                 { 
InBlock.gif                         UserInfo info = instance.Read(1); 
InBlock.gif                         Assert.NotNull(info); 
InBlock.gif                 } 
InBlock.gif                 [Test] 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 更新用户信息 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="info">用户实体</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Update() 
InBlock.gif                 { 
InBlock.gif                         UserInfo info = instance.Read(1); 
InBlock.gif                         info.RealName = "测试" + DateTime.Now.Millisecond.ToString(); 
InBlock.gif                         instance.Update(info); 
InBlock.gif                 } 
InBlock.gif                 [Test] 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 删除用户 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="userId">用户编号</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void DeleteByID() 
InBlock.gif                 { 
InBlock.gif                         int userId = instance.GetMaxUserId(); 
InBlock.gif                         instance.Delete(userId); 
InBlock.gif                 } 
InBlock.gif    
InBlock.gif                 [Test] 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 删除用户 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="userId">用户实体</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public void Delete() 
InBlock.gif                 { 
InBlock.gif                         int userId = instance.GetMaxUserId(); 
InBlock.gif                         UserInfo info = instance.Read(userId); 
InBlock.gif                         Console.WriteLine("userid={0},username={1}", info.UserID, info.UserName); 
InBlock.gif                         instance.Delete(info); 
InBlock.gif                 } 
InBlock.gif         } 
InBlock.gif }

  上面的代码在NUnit2.5.3中测试通过。
 四、总结
 同样作为微软的ORM框架,我觉得Linq to SQL更像一个探路的,试探一下大家对官方ORM的反应,正因为如此Linq to SQL在对数据库种类的支持上仅仅支持SQL Server,但是作为一个产品系列Linq to XML、Linq to SQL让大家对XML和数据库的访问更加方便了,因此得到了很多开发人员的追捧。而ADO.NET Entity Framework由于出现较晚的原因(在.NET Framework SP1及更高版本中支持),所以对Linq to SQL的某些不足进行了改进,并且还提供了Linq to Entities技术。
 在ADO.NET Entity Framework提供了四种访问数据库的方法:Linq to Entitiess、Entity SQL、EntityKey及直接对数据库用SQL语句查询,多种访问方法为我们在不同场合下使用提供了方便,需要特别说明的是Entity SQL目前仅支持SELECT操作,而不支持CREATE/DELETE/UPDATE操作,具体出处见:How Entity SQL Differs from Transact-SQL
 从性能上考虑,对于拥有丰富数据库开发经验的程序员来说,使用ORM确实会比直接使用SQL语句要性能低些,因为不管是Linq to Entitiess还是Entity SQL都最终会转换成SQL交给ADO.NET执行,肯定比直接使用ADO.NET执行SQL语句要慢。对于没有经验的开发人员来说,它们之间差别不大——反正都是很慢。
 从开发速度和灵活性上考虑,使用ORM框架比使用ADO.NET开发速度要高,而且假如数据库发生了变化对代码的影响也较小(尽管没有人会频繁改变数据库折腾自己,但是在开发阶段更改数据库的可能性仍是存在的,毕竟不可能让设计做到百分之百完美),当然对数据库操作的灵活性是ADO.NET胜出了。
 从可维护性上考虑,使用ADO.NET因为灵活性大所以不同的程序员实现同样的功能可能代码相差较大,而使用同一种ORM框架时这种代码上的差别不会太大,便于维护。
 以前我一直拒绝ASP.NET MVC,而一直使用自己习惯的三层架构开发模式,在网站前台尽可能少的使用服务器控件更多地是采用模板替换法或者生成静态页面、在后台则尽可能使用服务器控件,这么做的目的是出于前台访问的用户数大、后台访问用户数少所以在前台尽可能使用运行高效的方式而在后台尽可能采取高效的开发方式。直到去年的时候维护别人的一个项目,我才逐渐体会到MVC的好处,那就是控制起来灵活并且维护起来相对方便一些。
 如果仅仅追求运行效率,那么只有机器语言就足够了;如果除此之外还希望能兼顾一下开发效率,那么C足够了;如果除此之外还希望兼顾一下代码重用,那么C++也能满足了;如果除此之外,还希望更健壮避免直接操作内存,那么Java也是可以的;如果除此之外还希望更多更灵活的功能,那么C#是可以的......
 总之,每一种后出现的新生事物都是借鉴了它的前辈成功之处的,特别是在前辈的最成功之处,但是由于在某些地方太过关注,所以它在其它方面又会有一些不足,但是这些不足又是可以通过其它方式相对较容易解决的,甚至在某些情况下根本可以忽略。比如在中国大部分的程序员不用太关注是否提供跨平台支持,因为中国大部分公司都是用的Windows;在中国的相当部分程序员不用太关注性能问题,因为他们开发的产品从投入使用到最后停止运行过程中产生的数据单表记录超过百万的都不多。
 如何选择合适的技术,取决于我们队将要运行的环境的判断,这来自于经验分析。











本文转自周金桥51CTO博客,原文链接:http://blog.51cto.com/zhoufoxcn/313309 ,如需转载请自行联系原作


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
25046 0
使用SSH远程登录阿里云ECS服务器
远程连接服务器以及配置环境
13420 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
18625 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
20345 0
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
17121 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
13883 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
21616 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
18704 0
+关注
10145
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载