[VS2010] ADO.NET Entity Framework 新功能:永续保存无知对象 (Persistence-Ignorant Object) Overview

Posted petewell

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[VS2010] ADO.NET Entity Framework 新功能:永续保存无知对象 (Persistence-Ignorant Object) Overview相关的知识,希望对你有一定的参考价值。

ADO.NET Entity Framework 的新功能:永续保存无知对象。可以说是 Entity Framework 划时代的新功能,颠覆一般的数据组件/DAL 与数据库间的交互方式。


前一篇文章介绍了 ADO.NET Entity Framework 的模型优先设计 (Model First Design) 功能,有没有觉得 .NET Framework 4.0 中的 ADO.NET Entity Framework 进步了很多呢?如果你这样就满足了,那接下来的东西你看了可能会像某啤酒广告的女主角们那样的尖叫~

技术图片


一般在设计数据类的时候,大多都是以一个纯类 (轻量级类,只声明必要的属性代表字段,并没有和其他对象交互),包含几个只针对数据做处理的属性或方法等等,若要使用它和数据库连结时,只能在里面做一些 Property Mapping,并且另外撰写数据存取的 ADO.NET 程序,这个动作只要是当过应用程序开发人员,就会觉得如呼吸般自然 … 长久以来都是如此,没有一次例外。但 ADO.NET Entity Framework 2.0 试图将这个局面颠覆过来,开发人员可以直接使用纯类对象来生成数据结构,并且由 Entity Framework 代为建立数据库以及表格,这个方式可是以前 Visual Studio 开发人员前所未见的。这个方法在 Java 阵营中已经有一些实践品,而在 Java 阵营中对轻量级的数据对象一个特别的名词:POJO (Plain-old Java Object),在 .NET 阵营也有一个相对的名词,叫 POCO (Plain-old CLR Object),用途和 POJO 差不多,但微软给了一个笔者觉得很难翻的名词: Persistence-Ignorant Object,若直接翻译会变成 “保存无知型对象”,蛮拗口的,在官方翻译未出来前,就暂时先翻成 “无差别保存对象” (编按:在 "软件构筑美学" 一书中,将此词翻译为 "永续保存无知",笔者认为这个词翻的还不错,所以引用)?好了,因为 Persistence-Ignorant Object 具有不必事先在 DBMS 中建立实例数据库,就可以利用 Entity Framework 的 DDL Generation 功能将 POCO 对象结构转换成实例数据结构以存入数据库中的能力。

笔者认为永续保存无知对象在 ADO.NET Entity Framework 乃至于 ADO.NET 甚至是整个 .NET Framework 的 Data Access 机制而言,都是一项划时代的创新,它将数据存取组件设计的刻板印象完全的改变了,没想到只使用几个属性的声明就可以生成一个完成的数据结构,这可是许多开发人员梦寐以求的功能啊,笔者一开始看到这个功能时也是眼睛一亮,试过以后更觉得它是超级好物啊~

也许这样看起来还是有点抽象,实际走一次例子就知道了。不过在做例子前,请先看看环境是否符合:

A. 已安装 Visual Studio 2010

B. 下载并安装 ADO.NET Entity Framework Feature CTP2 : http://www.microsoft.com/downloads/details.aspx?FamilyID=13FDFCE4-7F92-438F-8058-B5B4041D0F01&displayLang=en

C. 已安装 SQL Server (最好是非 Express 版本,但 Express 版也无妨)

前置作业符合后,请依下列步骤执行:

1. 在 Visual Studio 中先建立一个 AdoEF_PocoExampleLibrary 类库项目,并且加入下列类声明程序 (可同在一个类库文件或是分成个别的文件):

public class Blog
?? public Blog()
?? public int ID get; set;
?? public string Name get; set;
?? public string Url get; set;
?? public User Owner get; set;
?? public ICollection Posts get; set;

public class Comment

?? public Comment()
?? public int ID get; set;
?? public string Title get; set;
?? public string Body get; set;
?? public Person Author get; set;
?? public Post Post get; set;
?? public DateTime Created get; set;
?? public DateTime? Posted get; set; ????

public class Person

?? public int ID get; set;
?? public string Firstname get; set;
?? public string Surname get; set;
?? public string EmailAddress get; set;
?? public ICollection Comments get; set;

public class Post

?? public Post()
?? public int ID get; set;
?? public string Title get; set;
?? public string Body get; set;
?? public string PermaUrl get; set;
?? public DateTime Created get; set;
?? public DateTime? Posted get; set;
?? public User Author get; set;
?? public User Poster get; set;
?? public Blog Blog get; set;
?? public ICollection Comments get; set;
?? public int BlogID get; set;

public class User : Person

?? public string Password get; set;
?? public ICollection Blogs get; set;
?? public ICollection AuthoredPosts get; set;
?? public ICollection PostedPosts get; set;

2. 在 Visual Studio 中建立一个 AdoEF_PocoExampleClient 主控台项目,先新增一个 BloggingModel 类,并将下列程序加入:

using System.Data.Entity;
using System.Data.EntityClient;
using System.Data.EntityModel;
using System.Data.Objects;

public class BloggingModel : ObjectContext

?? public BloggingModel(EntityConnection connection)
?????? : base(connection)
??
?????? DefaultContainerName = "BloggingModel";
??

??? public IObjectSet Blogs
??
?????? get return base.CreateObjectSet();
??

??? public IObjectSet People
??
?????? get return base.CreateObjectSet();
??

??? public IObjectSet Comments
??
?????? get return base.CreateObjectSet();
??

??? public IObjectSet Posts
??
?????? get return base.CreateObjectSet();
??

3. 在 AdoEF_PocoExampleClient 项目中加入一个 BlogDemo 类,并将下列程序加入(其中红字为数据库连线字符串,但 initial catalog 可以指定成目前还没建的数据库名称,若你已经有 Blogs 数据库,请将 initial catalog 的名称改一下,否则执行以后,你原有的 Blogs 数据库会被删掉):

using System.Data.Entity;
using System.Data.EntityClient;
using System.Data.EntityModel;
using System.Data.Objects;
using Microsoft.Data.Objects;

class BlogDemo

?? public static void Run()
??
?????? var builder = new ContextBuilder();
?????? RegisterConfigurations(builder);
?????? var connection = new SqlConnection("initial catalog=Blogs; integrated security=SSPI");

??????? using (var ctx = builder.Create(connection))
??????
?????????? if (ctx.DatabaseExists())
?????????????? ctx.DeleteDatabase();
?????????? ctx.CreateDatabase();
?????????? var EfDesign =
?????????????? new AdoEF_PocoExampleLibrary.Blog
??????????????
?????????????????? Name = "EF Design",
?????????????????? Url = "http://blogs.msdn.com/efdesign/",
?????????????????? Owner = new AdoEF_PocoExampleLibrary.User
??????????????????
?????????????????????? ID = 1,
?????????????????????? Firstname = "Johnny",
?????????????????????? Surname = "Miller",
?????????????????????? EmailAddress = "johnnyM@hotmail.com",
?????????????????????? Password = "Viking"
??????????????????
?????????????? ;

??????????? ctx.Blogs.AddObject(EfDesign);
?????????? var post = new AdoEF_PocoExampleLibrary.Post
??????????
?????????????? Title = "Hello",
?????????????? Blog = EfDesign,
?????????????? PermaUrl = EfDesign.Url + "/2009/08/Hello",
?????????????? Body = "....",
?????????????? Author = EfDesign.Owner,
?????????????? Poster = EfDesign.Owner,
?????????????? Created = DateTime.Today,
?????????????? Posted = DateTime.Today,
?????????? ;

??????????? ctx.Posts.AddObject(post);
?????????? var comment = new AdoEF_PocoExampleLibrary.Comment
??????????
?????????????? Title = "RE:" + post.Title,
?????????????? Body = "Welcome to the world of blogging Johnny...",
?????????????? Created = DateTime.Now,
?????????????? Posted = DateTime.Now,
?????????????? Post = post,
?????????????? Author = new AdoEF_PocoExampleLibrary.Person
??????????????
?????????????????? ID = 2,
?????????????????? Firstname = "Vincent",
?????????????????? Surname = "Chase",
?????????????????? EmailAddress = "vinny@hotmail.com",
??????????????
?????????? ;

??????????? ctx.Comments.AddObject(comment);
?????????? ctx.SaveChanges();

??????????? AdoEF_PocoExampleLibrary.Blog blog = ctx.Blogs.Single();

??????????? foreach (var entry in blog.Posts)
??????????
?????????????? Console.WriteLine(entry.Title);
?????????????? Console.WriteLine(entry.Author.Firstname);
??????????
??????
??

??? static void RegisterConfigurations(ContextBuilder builder)
??
?????? builder.Configurations.Add(new CommentConfiguration());
?????? builder.Configurations.Add(new BlogConfiguration());
?????? builder.Configurations.Add(new PostConfiguration());
?????? builder.Configurations.Add(new PersonConfiguration());
?????? builder.Configurations.Add(new UserConfiguration());
??

4. 在前一步的程序的下方,加入下列的程序:

public class CommentConfiguration : EntityConfiguration

?? public CommentConfiguration()
??
?????? Property(c => c.ID).IsIdentity();
?????? Property(c => c.Title).HasMaxLength(103).IsRequired();
?????? Property(c => c.Body).IsRequired();
?????? // 1 to * relationships???????????
?????? Relationship(c => c.Author).IsRequired();
?????? Relationship(c => c.Post).IsRequired();
?????? //Register some inverses???????????
?????? Relationship(c => c.Post).FromProperty(p => p.Comments);
?????? Relationship(c => c.Author).FromProperty(u => u.Comments);
??

public class BlogConfiguration : EntityConfiguration

?? public BlogConfiguration()
??
?????? Property(b => b.ID).IsIdentity();
?????? Property(b => b.Name).HasMaxLength(100).IsRequired();
?????? Relationship(b => b.Owner).IsRequired();
?????? //Register some inverses???????????
?????? Relationship(b => b.Owner).FromProperty(u => u.Blogs);
?????? Relationship(b => b.Posts).FromProperty(p => p.Blog);
??

public class PostConfiguration : EntityConfiguration

?? public PostConfiguration()
??
?????? // Make the PK store generated???????????
?????? Property(p => p.ID).IsIdentity();
?????? // Convert some ‘0..1 to *‘ relationships into ‘1 to *‘???????????
?????? Relationship(p => p.Author).IsRequired();
?????? Relationship(p => p.Blog).IsRequired();
?????? Relationship(p => p.Poster).IsRequired();
?????? // Setup some facets???????????
?????? Property(p => p.Body).IsRequired();
?????? Property(p => p.PermaUrl).HasMaxLength(200);
?????? Property(p => p.Title).HasMaxLength(100);
?????? // Register some Inverses???????????
?????? Relationship(p => p.Author).FromProperty(u => u.AuthoredPosts);
?????? Relationship(p => p.Comments).FromProperty(c => c.Post);
?????? Relationship(p => p.Poster).FromProperty(p => p.PostedPosts);
?????? //BlogID is a FK property and Blog is a navigation property backed by this FK????
?????? Relationship(p => p.Blog).FromProperty(b => b.Posts).HasConstraint((p, b) => p.BlogID == b.ID);
??

public class PersonConfiguration : EntityConfiguration

?? public PersonConfiguration()
??
?????? Property(p => p.ID).IsIdentity();
?????? Property(p => p.Firstname).HasMaxLength(100);
?????? Property(p => p.Surname).HasMaxLength(100);
?????? Property(p => p.EmailAddress).HasMaxLength(200);
?????? MapHierarchy(
?????????? p => new
??????????
?????????????? pid = p.ID,
?????????????? email = p.EmailAddress,
?????????????? fn = p.Firstname,
?????????????? ln = p.Surname,
??????????
?????? ).ToTable("People");
??

public class UserConfiguration : EntityConfiguration

?? public UserConfiguration()
??
?????? Property(u => u.Password).HasMaxLength(15).IsRequired();
?????? Relationship(u => u.AuthoredPosts).FromProperty(p => p.Author);
?????? Relationship(u => u.PostedPosts).FromProperty(p => p.Poster);
?????? MapHierarchy(
?????????? u => EntityMap.Row(
?????????????? EntityMap.Column(u.ID, " u i d"),
?????????????? EntityMap.Column(u.Password)
?????????????? )
?????? ).ToTable("Users");
??

5. 在 AdoEF_PocoExampleClient 的 Program.cs 中,加入下列的程序:

class Program

?? static void Main(string[] args)
??
?????? BlogDemo.Run();
??

6. 若你所使用的数据库是 SQL Server (非 Express 或 Compact Edition),可将 SQL Profiler 先启动并进入监听模式。

7. 按 F5 以调试器执行或按 CTRL+F5 直接执行,正常情况下窗口会出现以后消失。此时请打开 SQL Server Management Studio 并连到本机服务器中,即可以看到新的 Blogs 数据库。

技术图片

8. 若在前面有启动 SQL Profiler 监听,则可以将它停止后,看看 Entity Framework 做了什么事:

技术图片

如何,是不是有想要尖叫的感觉呢?有了这样的机制,Entity Framework 更向成熟的 ORM Framework 迈进一大步了。

由于这个功能太大,一回文章介绍不完,因此笔者下回再继续深入介绍这个神奇的功能。

参考数据:

Updated Feature CTP Walkthrough: Code Only for Entity Framework

http://blogs.msdn.com/adonet/archive/2009/11/12/updated-feature-ctp-walkthrough-code-only-for-entity-framework.aspx

范例程序下载:

http://blogs.msdn.com/adonet/attachment/9921786.ashx

原文:大专栏  [VS2010] ADO.NET Entity Framework 新功能:永续保存无知对象 (Persistence-Ignorant Object) Overview


以上是关于[VS2010] ADO.NET Entity Framework 新功能:永续保存无知对象 (Persistence-Ignorant Object) Overview的主要内容,如果未能解决你的问题,请参考以下文章

ADO.NET Entity Framework 和标识列

ADO.NET Entity Framework 如何查看T

如何从 ADO.NET Entity Framework 中的模型生成表?

我的VS2010中找不到ado.net实体数据模型,谁能帮忙解决一下

VS2010里创建ado.net实体模型,根据实体对象创建数据库, 会生成一个.edmx.sql这个文件

ADO.NET Entity Framework