用ObjectSpaces重建IBuySpy的数据访问层

object|访问|数据

ObjectSpaces这个ORM框架可能已经被大家听过N次了,它诞生很早,但开发周期拖了很长,虽然很早它的测试版本就已经有人使用了,但只到.Net Framework 1.2才计划正式将它包含其中,并放在了Object.Data.ObjectSpaces这个NameSpace中。
  
  
  
  ObjectSpaces的流传版本也是甚多,被很多人研究过的一个EAP(Early Adopter Preview)版的版本号是1.0.1081,我在Gotdotnet.com里面看过一个1.0.3328.4的版本做的东西,这里用的这个ObjectSpaces是现在大家普遍使用的.Net Framework 1.2 Alpha测试版里面带的,版本号同.Net Framework保持一致,1.2.30703.27。
  
  
  
  从版本号的变更就可以看出,ObjectSpaces从开始到现在变化很大。上面提到的三个版本都各有差别,而且差别不小。现在最新的这个版本我想应该和最终版本差别不会很大了。我以前的一篇文章就是基于EAP版本的,比现在的简单不少。
  
  
  
  进入正题:在IBuySpy的架构中,实际上是没有BLL(商业逻辑层)的,甚至没有创建Entity Class,数据通过DAL(数据访问层)从数据库中获得,然后将DataSet或者DataReader直接从DAL传递给构成IBuySpy页面的Module的ascx文件,再直接绑定到DataList之类的web control上。
  
  
  
  我们这里将IBuySpy的Announcement模块的DAL用ObjectSpaces重新写过:
  
  
  
  一、先来看看IBuySpy原来的Announcements模块
  
  
  
  DAL:AnnouncementsDB.cs文件
  
  界面控件页面:用于显示的Announcements.ascx控件和用于新增修改的EditAnnouncements.aspx页面
  
  
  
  里面都是最最标准的写法,没什么讲的。
  
  
  
  二、Entity Class
  
  
  
  新创建一个Announcement类和一个AnnouncementCollection集合类,也没什么讲的。
  
  
  
  三、建立ObjectSpaces的RSD、OSD、MSD
  
  
  
  ObjectSpaces的核心就是用来描述Schema的三个xml文件:
  
  一个描述数据库表结构的Relational Schema Definition,一个描述实体类结构的Object Schema Definition,和一个描述表结构和实体类映射关系的Mapping Schema Definition。
  
  用ObjectSpace最主要(也是最烦人)的工作就是把这三个Schema写出来。EAP版里面还只有一个xml文件要写,现在要写三个了L。
  
  
  
  AnnouncementRSD.xml
  
  AnnouncementOSD.xml
  
  AnnouncementMSD.xml
  
  
  
  四、重写DAL
  
  
  
  创建一个新的类文件AnnouncementOSDB.cs,包含一个新的类AnnouncementOSDB,里面的方法签名对照着IBuySpy原本的AnnouncementDB类就行了。原本的AnnouncementDB是用ADO.NET,返回DataSet、DataReader,我们的AnnouncementOSDB就用ObjectSpaces,返回实体集合类或实体类。
  
  
  
  根据moduleId返回Announcement集合:
  
  public AnnouncementCollection GetAnnouncements(int moduleId)
  
   {
  
   ObjectSpace os = new ObjectSpace(_sMapFilePath, _conn);
  
   // 条件是ModuleID等于参数moduleId,ExpireDate大于当前时间
  
   ObjectQuery query = new ObjectQuery(typeof(Announcement), "ModuleID = " + moduleId.ToString() + " and ExpireDate > #" + DateTime.Now.ToString() + "#");
  
   // 取数据
  
   ObjectReader reader = os.GetObjectReader(query);
  
  
  
   AnnouncementCollection result = new AnnouncementCollection();
  
   // 从ObjectReader中取值不需要另外造型
  
   foreach (Announcement ann in reader)
  
   {
  
   result.Add(ann);
  
   }
  
  
  
   return result;
  
   }
  
  
  
  根据参数返回一个Announcement:
  
   public Announcement GetSingleAnnouncement(int itemId)
  
   {
  
   ObjectSpace os = new ObjectSpace(_sMapFilePath, _conn);
  
   ObjectQuery query = new ObjectQuery(typeof(Announcement), "ItemID = " + itemId.ToString());
  
   return (Announcement) os.GetObject(query);
  
   }
  
  
  
  根据参数删除一个Announcement:
  
   public void DeleteAnnouncement(int itemId)
  
   {
  
   ObjectSpace os = new ObjectSpace(_sMapFilePath, _conn);
  
   ObjectQuery query = new ObjectQuery(typeof(Announcement), "ItemID = " + itemId.ToString());
  
   Announcement ann = (Announcement) os.GetObject(query);
  
   os.MarkForDeletion(ann);
  
   os.PersistChanges(ann);
  
   }
  
  
  
  新增一个Announcement:
  
   public void AddAnnouncement(int moduleId, int itemId, String userName, String title, DateTime expireDate, String description, String moreLink, String mobileMoreLink)
  
   {
  
   Announcement ann = new Announcement();
  
   ann.SetModuleID(moduleId);
  
   ann.SetItemID(-1);
  
   ann.CreatedByUser = userName;
  
   ann.CreatedDate = DateTime.Now;
  
   …
  
  
  
   ObjectSpace os = new ObjectSpace(_sMapFilePath, _conn);
  
   os.StartTracking(ann, InitialState.Inserted);
  
   os.PersistChanges(ann);
  
   }
  
  
  
  修改一个Announcement:
  
   public void UpdateAnnouncement(int moduleId, int itemId, String userName, String title, DateTime expireDate, String description, String moreLink, String mobileMoreLink)
  
   {
  
   ObjectSpace os = new ObjectSpace(_sMapFilePath, _conn);
  
   ObjectQuery query = new ObjectQuery(typeof(Announcement), "ItemID = " + itemId.ToString());
  
   Announcement ann = (Announcement) os.GetObject(query);
  
  
  
   ann.CreatedByUser = userName;
  
   ann.Title = title;
  
   …
  
  
  
   os.PersistChanges(ann);
  
   }
  
  
  
  五、最后修改界面层
  
  
  
  原本界面层是把AnnouncementDB返回的DataSet绑定到Web Control上,只要改成将AnnouncementOSDB返回的实体集合类绑定到Web Control上就可以了,改动量很少很少。
  
  
  
  比如:
  
  原本将数据取出并绑定的代码(在Announcemenets.ascx.cs中):
  
  AnnouncementsDB announcements = new AnnouncementsDB();
  
  myDataList.DataSource = announcements.GetAnnouncements(ModuleId);
  
  myDataList.DataBind();
  
  只要将第一句改成:
  
  AnnouncementOSDB announcements = new AnnouncementOSDB();
  
  实际上就是改从哪个DAL取数据就OK了。
  
  
  
  六、讲讲ObjectSpaces
  
  
  
  ObjectSpaces的架构是这样的:
  
  ObjectSpace类管理数据映射,它负责(隐形的通过ObjectEngine)从数据源(IDbConnection或者ObjectSources)取数据和将数据更新回数据源(更新时会自动隐形启用Transaction)。它通过ObjectSpace.GetObject()返回单个对象,通过ObjectSpace.GetObjectSet()返回ObjectSet对象(这个对象类似于DataSet,表示一组数据对象),通过ObjectSpace.GetObjectReader()返回ObjectReader对象(这个对象类似于DataReader,是一个快速的forward-only的数据对象读取器)。它通过内含的ObjectContext来维护数据对象的原始值和监视数据对象的值的修改。
  
  
  
  我上面的代码演示目的是为了展示ObjectSpaces,并没有完整的给IBuySpy加一个BLL。我也没有演示数据之间的Relations,ObjectSpaces可以支持非常丰富的Relations,OneToOne、ManyToMany、OneToMany等等,而且也提供了LazyLoading(在真正需要使用Relation的数据的时候才真正去取这些数据)。
  
  
  
  不过如果你也试着用ObjectSpaces来重建你的项目中的DAL,我不知道你的感觉会不会和我一样,那就是“比现在更麻烦…”。比如,不支持存储过程(难道支持而文档里面不提一句吗?EAP版本还支持的),手工写RSD、OSD、MSD太繁琐了(PDC2003上出现过一个Mapper Utility,希望Whidbey会提供自动化工具),灵活性降低不少(所有ORM框架的问题)。

时间: 2024-11-10 00:39:49

用ObjectSpaces重建IBuySpy的数据访问层的相关文章

实战 .Net 数据访问层 - 23

访问|数据 u 使用现成的框架 Ø 首选当然是.NET Framework即将正式推出的ObjectSpaces! Ø 如果希望Total Solution,Borland ECO就是最佳选择! Ø 其它 n 开源项目推荐使用OPF(国外) n 商业产品推荐使用Grove(国内) u 设计自己的持久层 Ø 如果希望自己设计轮子,那么,最好的参考资料莫过于这篇文章:http://www.ambysoft.com/persistenceLayer.pdf Ø 它山之石,可以攻玉 此处之它山,非J2E

实战 .Net 数据访问层 - 1

访问|数据 实战 .Net 数据访问层 l 特别说明 本篇实战共分23段,非作者有意如此,乃受CSDN发表文章之64K所限. 虽然有几段根本没有达到64K,但估计是HTML Source超过了这个范 围,所以也不得不单独分段(大都是源代码),请大家谅解. 如果有朋友需要完整文档,请发邮件给我: mailto:xuefeng.zhang@bearingpoint.com l 引言 这次的讨论是上一部分"剖析 .Net 下的数据访问层技术"的一个续,但也可独立成章,为突出主题,作者就特意换

设计.NET应用程序数据访问层五大原则

程序|访问|设计|数据 摘要:大多数使用.NET框架组件工作的开发人员的一个核心工作是实现数据访问功能,他们建立的数据访问层(data access layer)是应用程序的精华部分.本文概述了使用Visual Studio .NET和.NET框架组件建立数据访问层需要考虑的五个想法.这些技巧包括通过使用基类(base class)利用面相对象技术和.NET框架组件基础结构,使类容易继承,在决定显示方法和外部界面前仔细地检验需求. 如果你正在建立以数据为中心(data-centric)的.NET

ASP.NET2.0数据操作之创建数据访问层(1)

asp.net|创建|访问|数据 导言 作为web开发人员,我们的生活围绕着数据操作.我们建立数据库来存储数据,写编码来访问和修改数据,设计网页来采集和汇总数据.本文是研究在ASP.NET 2.0中实现这些常见的数据访问模式之技术的长篇系列教程的第一篇.我们将从创建一个软件框架开始,这个框架的组成部分包括一个使用强类型的DataSet的数据访问层(DAL),一个实施用户定义的业务规则的业务逻辑层(BLL),以及一个由共享页面布局的ASP.NET网页组成的表现层.在打下这个后端的基础工作之后,我们

ASP.NET2.0数据操作之创建数据访问层(2)

asp.net|创建|访问|数据 这最后一个复选框,"生成DB直接方法(GenerateDBDirectMethods)",如果选了的话,会为TableAdapter自动生 成Insert(),Update(),和Delete()方法.如果你不选这个选项 的话,所有的更新都需要通过TableAdapter唯一的Update()方法来实现,该方法接受一个强类型的DataSet,或者一个DataTable,或者单个DataRow,或者一个DataRow数组.(假如你 在图9所示的高级属性里

ASP.NET2.0数据操作之创建数据访问层(4)

asp.net|创建|访问|数据 第五步:完成数据访问层 注意,ProductsTableAdapters类从Products表中返回的 是CategoryID和SupplierID的值,但并不包括Categories表 的CategoryName字段和Suppliers表的CompanyName字段,尽管当 我们显示产品信息时,这些很可能是我们想要显示的字段.我们可以扩充TableAdapter的起始方 法GetProducts()来包含CategoryName和CompanyName字段的值

C#中动态数组(ArrayList )应用实例子(三层代码:数据访问层,业务层,页面层)

动态|访问|数据|数组|页面|应用实例 用绑定一个 DataList 的三层代码说明一下: DAL 数据访问层代码:------------------------------------------------------------//绑定IDList,显示所有人员列表  public DataSet SelectIDListAll()  {       string Str = "select p_number,p_name from t_people";        Data

剖析 .Net 下的数据访问层技术(一)

访问|数据 l 引言 自从 .NET 真正走入开发人员那天起,"效率"两个字就一直成为众多程序员津津乐道的话题.无论是从开发模式(Cross Language).系统框架(.NET Framework),还是各种使用方便的工具(VS.NET),无一不体现出了它的胜人一筹. 同时,在另一方面,.NET 是否可以真正胜任企业级应用(Enterprise Application)开发的重任,却依然争论不断,褒贬不一. 通常来说,对于一个企业级应用,需要考虑的方面很多,如安全.性能.伸缩性.易

轻松搞定数据访问层[续]

访问|数据 数据库表 Tbl_Teacher 数据字段名称 类型 说明 teaID Int 自动编号 teaCode Char(20) 教师员工号 teaName Nchar(10) ? teaGender Bit ? teaNation Nchar(6) ? teaAge TinyInt ? Tbl_Student 数据字段名称 类型 说明 stuID Int 自动编号 stuCode Char(20) 学生证号 stuTeacherCode Char(20) 班主任的员工号 stuName