当前位置: 首页 > news >正文

ORM in .NET 3.5

出处:http://i.aspx1.com/showtopic-710.htm

作者:Luke Stratman
原文链接:http://dotnetslackers.com/articles/net/ORMInNET35.aspx
Introduction
ORM,对象-关系映射,在现代面向对象编程语言中,其中实现起来比较棘手的事。它包括摒弃传统的数据存储机制:这里没有(或很少)专门的、预编译的代码,涉及读(写)对象从(到)数据库或其它后备存储中。作为替代,涉及访问后备存储的逻辑在运行时被决定,通过运用一系列反射和特性机制修饰正在考虑的业务对象。许多已经建立的工程和框架试图提出这个观念并取得了多方面的成功。这篇文章覆盖了:概括介绍ORM理念,一种.NET3.5携带的途径,及其和其他框架的比较。

In the beginning...

在.NET3.5之前,当你需要把你的业务对象从数据库读取或写入时,你有以下几个选择:

1.
自己动手 – 这意味着你不需要任何框架,不需要自动生成任何代码。数据库结构和.NET类都是手工建立的,数据访问层也是如此。虽然这将会提供最终的执行,但是当对象或数据库结构改变时,它将是乏味的(包括复制大量重复代码),易出错的,难以维护的。

2.
自动生成类和数据访问层 – 这就是自动生成工具CodeSmith和MyGeneration到来的缘由:你在你的数据库中指明它们,它将自动生成.NET类和数据访问层。看看第一条选择,这不是真正的ORM:你仍然有预编译代码负责访问数据库用来读取或写入对象的数据。不过,它的自动生成代码机制在这方面做出了正确的一步,排除了当创建类和数据访问层时易出错的人为因素。

3.
运用真正的ORM框架 – 在先前的.NET框架版本中,这里有一些知名的ORM框架可获取,包括NHibernate和Gentle.NET。就如事先提到的,ORM移除了专注于数据存储的代码和在运行时检查一个对象来决定从数据库读取或写入这个对象需要做哪些工作。特性用来修饰类和类的属性,用以给出标识类和数据库的映射。一个操作的真实SQL是基于这些特性动态生成的。经常有一个代码自动生成组件在这些框架中用来从数据库结构中生成业务对象类,但是关注于数据访问的代码没有生成。


Major Malfunctions(缺点) with ORM

所有这些动态的,运行时的SQL生成机制听起来不错,是么?并非如此:ORM有一些严重的缺点。第一个就是性能问题,因为在任何时候你把反射引入并开始动态生成SQL,你会遭遇减速。ORM永远不会和自己手动处理一样快:没有替代品可以替代“手拧”存储过程和预编译所有数据访问逻辑。另一个缺点是ORM对极度复杂的数据库处理的不好。当设计很多约束和关系跨越多个表的复杂数据库时,这经常有必要包括中间表去把各种实体关联起来,这从RDBMS的立场看似乎不错,但是在一个面向对象环境中看起来有点牵强。这也将导致难以理解自动生成的类。紧记,RDBMS和面向对象环境是根本不同的,它们各自拥有一套设计和性能考量。在一个环境中动作良好并不意味在另一个环境中亦如此。话虽如此,ORM以可维护、干净的、易懂的代码的方式提供正确的使用总是比较牵强的。

LINQ, DataContexts, and general ORM in .NET 3.5


目前为止,你对ORM已经有了整体的了解和它潜在的陷阱,让我们探讨一下Microsoft在.NET3.5中是如何接近这个观念的。它提出了一个不同的途径去挑战ORM,它并不把焦点集中在对象模型、关系模型,它提供给我们一套全新的思路去访问和查询数据,这并不局限于关系数据。通过这个途径,.NET3.5的ORM能力发展成了这个新的数据访问架构,几乎如同副作用一般,取代了原来的焦点。他们是怎样做到的?LINQ。它代表集成查询语言,Microsoft想把它变成在.NET框架中筛选数据的途径。它的结构与我们平时写SQL语句很类似,它非常简单,并且拥有对强类型面向对象语言强有力的SQL查询语法。实际的反对者,然而,是它不仅仅局限于关系数据:只要实现了IEnumerable和IQueryable接口,就能使用LINQ。这里有一个例子,你可以从中知道它的能力:

List<string> elements = new List<string>(){"Iridium","Einsteinium","Polonium"};IEnumerable<string> results = from element in elementswhere element.Contains("n")select element;
这只是一个简单的从elements中查询包含字母”n”的普通字符串例表实例。然而在之前你不得不命令式地完成这项功能,也就是你将不得不写代码迭代集合来驱动查询,现在你可以直接地完成相同的功能。基本上,你陈述你要做什么来替代如何去做。当用这种语法,这种途径固有地不太会出错。它同样也支持提及的智能感知,所以当你从事于LINQ编程时,你一点也不会在Visual Studio中损失轻松使用的特征。

那么,我们来看看LINQ是如何适合ORM的。第一,这里有一个代码生成组件:LINQ并没有避开它由于你不得不定义映射数据库中的关系数据为类似于面向对象世界的类。为了做到这一点,Microsoft提供一个叫做SQLMetal的工具。为了使用它,仅仅打开Visual Studio命令行提示(Start->Programs->Visual Studio 9.0->Visual Studio Tools->Visual Studio Codename Orcas Command Prompt),然后打上sqlmetal来看看它的选项。它非常简单:你所需要做的是指明它的数据库,告诉代码文件的名称和(或)你想要生成的DBML文件。我创建了一个简单的名为LinqTest的数据库,它包含两张表:Person和PersonAddress。PersonAddress有一名为personId的列,它是一个外部键,用来关联Person表中相匹配的列。所以,我运用如下命令产生ORM类:

sqlmetal /database:LinqTest /language:csharp /code:LinqTest.cs


从这个过程得到的代码结果中包含两套类:DataContext类和一系列与数据库中表相符的对象类。对象类非常简单:它们反映出数据库中的表,其中的属性代表每个列。每个类和其属性都被特性修饰,来描述和数据库之间的映射,这和其他ORM框架类似。一个很好的提高是我并没有在任何地方发现,除非每个对象类自动执行INotifyPropertyChanging和INotifyPropertyChanged,这意味着它们暴露了当一个属性的值改变时允许外界类去响应的事件。为了促进这一点,要点是每个属性包装到OnPropertyChanging()和OnPropertyChnaged回调方法,依次触发事件处理函数,如果它们设置了。另一个漂亮的特征是这样一个事实,所有由SQLMetal产生的类都是部分类,它们仅仅实现必要的核心功能。这意味着你可以通过分离代码文件自由的添加类功能,不需要更新自动生成的输出。DataContext类提供链接到包含将用于移植到对象类的数据的后备存储的服务(在这个例子里是数据库)。你通过一个连接字符串或一个初始化了的数据连接对象来得到它的构造器,依次,它暴露一系列泛型属性Table<>,其中每个都代表数据库中的一张表。这些Table<>属性是真正给予LINQ力量的:Table<>类是完全支持LINQ的,它负责于扮演LINQ与数据库间的接口,将LINQ语法翻译成必要的SQL语句,从而从数据库中检索你的数据。同样地对于先前的例子,让我们来看看另一个使用Table<>属性的LINQ查询:

LinqTest linqTest = new LinqTest("Data Source=DDVPC01""SQLEXPRESS;Initial Catalog=LinqTest;Integrated Security=True");IEnumerable<Person> results = from person in linqTest.Personwhere person.FirstName.StartsWith("L")select person;


所有这些讲述了ORM实现是如何地困难,鉴于在.NET3.5中其他的看起来有点虎头蛇尾:它对于有SQL经验的非常容易懂,它完全集成于语言及开发环境,而且它令人惊讶的快。想添加一个新Person信息到数据库?没问题:

linqTest.Person.Add(new Person(){FirstName = "Mike",LastName = "Smith"});linqTest.SubmitChanges();

只要你调用必要的Table<>属性的Add()方法,做完这步之后,调用DataContext类的SubmitChanges()方法。

Wrapping it up 总结

我希望这篇文章能给你一些好的建议对于在.NET3.5中处理ORM。这并不是解决所有挑战数据访问的银弹,但就如任何一个优秀的程序员所知,这从来就没有。当数据库结构很复杂并且性能至关重要时,这里就没有办法替代手工写代码,调整.NET数据访问代码和SQL逻辑。但是,至于明确的结构和.NET中一般的数据过滤,LINQ表现为一种新的,诡秘的ORM实现。


posted on 2008-05-03 00:37 nicholas.sun
本文来自: ASP.NET学习门户(http://www.aspx1.com) 详细出处参考:http://i.aspx1.com/showtopic-710.htm

相关文章:

  • jupyter notebook 选择新的 conda 环境
  • python 生成字母图片
  • 新爹手记之起名篇
  • 使用LumaQQ来开发QQ机器人
  • 图信号处理——拉普拉斯矩阵
  • SPS中计算值公式函数简介
  • 台式机核显和独显切换
  • SPS常见公式示例
  • ModuleNotFoundError: No module named 'torch_sparse.unique_cuda'
  • ModuleNotFoundError: No module named 'torch_scatter.cuda'
  • 反击arp病毒攻击
  • 数据降维与可视化——t-SNE
  • 单例模式完全剖析(1)---- 探究简单却又使人迷惑的单例模式
  • 使用 texttable可视化
  • 单例模式完全剖析(2)---- 探究简单却又使人迷惑的单例模式
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • avalon2.2的VM生成过程
  • eclipse的离线汉化
  • JavaScript 基础知识 - 入门篇(一)
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Mybatis初体验
  • MySQL数据库运维之数据恢复
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • Ruby 2.x 源代码分析:扩展 概述
  • 服务器之间,相同帐号,实现免密钥登录
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • kubernetes资源对象--ingress
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • $refs 、$nextTic、动态组件、name的使用
  • (Oracle)SQL优化技巧(一):分页查询
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (力扣)循环队列的实现与详解(C语言)
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (转)mysql使用Navicat 导出和导入数据库
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .Net 6.0 处理跨域的方式
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .Net IOC框架入门之一 Unity
  • .NET Micro Framework 4.2 beta 源码探析
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • @angular/cli项目构建--http(2)
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • @我的前任是个极品 微博分析
  • [1181]linux两台服务器之间传输文件和文件夹
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [BZOJ1008][HNOI2008]越狱
  • [C#基础知识系列]专题十七:深入理解动态类型
  • [CF703D]Mishka and Interesting sum/[BZOJ5476]位运算
  • [Golang]K-V存储引擎的学习 从零实现 (RoseDB mini版本)