不知道对EF感兴趣的并不多,还是我翻译有问题(如果是,恳请你指正),通过前几篇的反馈,阅读这个系列的人不多。不要这事到最后成了吃不讨好的事就麻烦了,废话就到这里,直奔主题。

2-2 从已存在的数据库创建模型

  问题

  有一个存在的数据库,它拥有表、也许还有视图、外键。你想通过它来创建一个模型。

  解决方案

  让我们设想,你拥有一个描述诗人(Poet)以及他们的诗(Poem),还有他们之间关系的数据库。如图2-7所示。

  

  图2-7 一个关于诗人及他们的诗的简单数据库

  从上图可以看出,一个诗人可能是一首或多首诗的作者,每首诗可以按其韵律来分类,韵律是诗句的基本模式。上图未显示数据库中将表连接在一起的视图,它让我们更容易的枚举诗人,诗和韵律。

  按下列步骤,将表、视图以及关系导入到模型:

    1、右键你的项目,选择Add(增加) ➤New Item(新建项)。

    2、选择Visual C#条目下的Data模板下的ADO.NET Entity Data Model(ADO.NET实体数据模型)。

    3、选择Generate from database 从一个已存在的数据库创建模型,点击Next(下一步)。

    4、可以选择一个已存在的数据库连接,也可以选择新建一个数据库连接,如果你选择新建,你将要选择数据库服务器、认证方式(Windwos or SQL Server)以及一个数据库。你一旦选择好,便可以点击Test Connection(测试连接)测试连接是否可用。测试好后,点击Next(下一步)。

        弹出的对话框中显示了数据库所有的表、视图以及存储过程。选择你希望包含在模型中的项。我们选择所有的表(Meter,Poem,Poet),视图(vwLibrary),然后勾选上确定所生成对象名称的单复数形式、在模型中包含外键列复选框。我们将会进一步对此时行讨论。图2-8展示了我们所做的选择。

  图2-8 选择表、视图包含进模型,勾选上确定所生成对象名称的单复数形式、在模型中包含外键列复选框

  当点击Finish(完成),向导会生成一个包含三张表和一个视图的模型。向导从数据库读取外键约束,并推导出Poet和Poem(s)之间的一对多关系,还有Meter和Poem(s)之间的一对多关系。

图2-9 概念模型

  图2-9展示了一个包含表Poet,Poem以及Meter、视图vwLibrary的模型。

  现在,你拥有了一个可以在代码中使用的模型。请注意, vwLibrary实体是基于数据中的视图vwLibrary的。在绝大多数据库中,视图是只读的,插入、删除、更新不被支持。在实体框架中也同样如此,实体框架把视图视为只读。你可以通过映射存储过程来解决基于视图的实体的创建、更新和删除动作。我们将在第六章对此进行演示。

  原理

  让我们一起来看导入向导为我们创建的模型。请注意,实体中已经包含了标量属性和导航属性。标量属性被映射到数据库表中列,导航属性却来至数据库中的表间关系。

  在数据库关系图中,一个poem拥有一个meter和一个poet(作者)。这符合Meter和Poet中的导航属性。如果我有一个Poem实体的实例,导航属性Poet将引用一个Poet实体的实例,导航属性Meter将引用一个Meter实体的实例。

  一个Poet可能是多首诗的作者,它其中的导航属性Poems包含一个Poem实体的实例集合。这个集合可能是空的,这代表该诗人还未创建任何一首诗。对于Meter实体,其中的导航属性Poems同样也是一个集合。该导航属性包含属于指定Meter的Poem实体实例的集合。SQL Server不支持在视图上创建关系,这在模型中反映为一个没有导向属性的vwLibrary实体。

  导入向导在包含集合的导航属性的名称单复数形式上表示得相当的聪明。当你右键实体去查看他的Properties(属性),你会看到每个实体的实体集的名称同样为复数形式。例如Poem实体的实体集名称为Poems. 这种自动添加复数利益于,勾选上确定所生成对象名称的单复数形式复选框。

  勾选在模型中包含外键列复选框选项,使外键也包含在了模型中。虽然看上去,在拥有导航属性的同时好像没有必要再拥有外键属性。对此,我们会在接下来的技巧中演示拥有一个可直接访问外键属性的好处。

  代码清单2-2,演示了如何在模型中创建Poet,Poem以及Meter实体的实例并将他们保存到数据为。同时也演示了,如何通过查询模型从数据库中获取到poets和poems。

代码清单2-2.在模型中插入和查询

  using (var context = new EF6RecipesContext()) {
var poet = new Poet { FirstName = "John", LastName = "Milton" };
var poem = new Poem { Title = "Paradise Lost" };
var meter = new Meter { MeterName = "Iambic Pentameter" };
poem.Meter = meter;
poem.Poet = poet;
context.Poems.Add(poem);
poem = new Poem { Title = "Paradise Regained" };
poem.Meter = meter;
poem.Poet = poet;
context.Poems.Add(poem);
poet = new Poet { FirstName = "Lewis", LastName = "Carroll" };
poem = new Poem { Title = "The Hunting of the Shark" };
meter = new Meter { MeterName = "Anapestic Tetrameter" };
poem.Meter = meter;
poem.Poet = poet;
context.Poems.Add(poem);
poet = new Poet { FirstName = "Lord", LastName = "Byron" };
poem = new Poem { Title = "Don Juan" };
poem.Meter = meter;
poem.Poet = poet;
context.Poems.Add(poem);
context.SaveChanges();
}
using (var context = new EF6RecipesContext()) {
var poets = context.Poets;
foreach (var poet in poets) {
Console.WriteLine("{0} {1}", poet.FirstName, poet.LastName);
foreach (var poem in poet.Poems) {
Console.WriteLine("\t{0} ({1})", poem.Title, poem.Meter.MeterName);
}
}
} // 使用视图 vwLibrary
using (var context = new EF6RecipesContext()) {
var items = context.vwLibraries;
foreach (var item in items) {
Console.WriteLine("{0} {1}", item.FirstName, item.LastName);
Console.WriteLine("\t{0} ({1})", item.Title, item.MeterName);
}
}

  代码清单2-2中第一个代码块,我们创建 了Poet,Poem以及Meter实体类型的实例,诗人John Milton,他的诗“Paradise Lost"以及该诗的韵律,该诗属于五步抑扬格-Iambic Pentameter(诗的一种韵律)。我们一旦创建Poem实体类型的实例peom,并设置poem的Meter属性指向meter实例,Poet属性指向poet实例。使用相同的方法,我们创建其它的实体及关系。一旦完成创建,我们就可以调用SaveChanges()方法生成并执行适当的SQL语句,在底层数据库中插入数据。

  代码清单2-2的输出发下:

Lord Byron
Don Juan (Anapestic Tetrameter)
Lewis Carroll
The Hunting of the Shark (Anapestic Tetrameter)
John Milton
Paradise Regained (Iambic Pentameter)
Paradise Lost (Iambic Pentameter)
Lewis Carroll
The Hunting of the Shark (Anapestic Tetrameter)
Lord Byron
Don Juan (Anapestic Tetrameter)
John Milton
Paradise Regained (Iambic Pentameter)
John Milton
Paradise Lost (Iambic Pentameter)

  在代码中,我们最开始创建实例poet,poem以及 John Milton第一首诗的韵律meter。一旦我们创建好,就可以设置poem的导航属性Meter为meter实例,Poet导航属性为poet实例.实例poem的所有设置已完成,调用Add()方法将其添加到上下文中。接下来的工作将由实体框架来完成,包括添加poem到poet实例的导航属性Poems集合中,添加poem到meter实例的导航属性Poems集合中。使用相同的步骤完成剩下的任务。为了缩减代码,我们复用了变量和实例。

  一旦创建完所有实例,并完成导航属性的初始化,我们就完成了一个对象图的创建。实体框架保持创建对象图的所有修改,这此跟踪是在数据库上下文中实现的。变量 context包含一个数据库上下文的实例(它的类型是DbContext),它是我们用来跟踪创建对象图所做修改的对象,调用其SaveChanges()方法,可以将所有修改发送到数据库中。

  接来可以查询模型,以验证我们保存在数据库的数据。我们使用了一个新的上下文对象以及使用LINQ to Entities来查询。我们本来可以重用之前的上下文对象,但是我们知道它已经在内存中有了对象图,接下来的查询都不会通过数据库就直接从内存中就获取了(译注:这样就达不到验证的目的了)。

  使用LINQ to Entities,我们查询出所有的诗人(poets),然后打印出每一位诗人的姓名,以及该诗人的每一首诗的详细信息。代码非常简单,但使用了两个嵌套的循环来实现。

  最后一段代码块使用VwLibrary实体,该实体基于vwLibrary视图。vwLibrary视图把表连接在一起使其扁平化以提供一个更清晰的视角。我们通过vwLibraties实体集查询每位诗人的相关信息时,仅需要一次循环。输出有略有不同,因为我们在每首诗中重复了诗人的的姓名。

  此示例中最后需要注意的是,我们没有通过视图vwLibrary插入poests,poems以及meters。因为在绝大多数的数据库中,视图是只读的。我在实体框架中,我们同样不能能过视图实体插入(或者更新、删除)实体。当然,我们将会在本书后面部分给你演示如何克服这个困难!

  本篇就到这里吧。弄饭吃去了。 如果你觉得不错的话,请点击右下角的 推荐,一来是给我动力,二来是分享给更多的人。谢谢。

 

实体框架交流QQ群:  458326058,欢迎有兴趣的朋友加入一起交流

谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/VolcanoCloud/

《Entity Framework 6 Recipes》翻译系列 (4) -----第二章 实体数据建模基础之从已存在的数据库创建模型的更多相关文章

  1. 《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型

    第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...

  2. 《Entity Framework 6 Recipes》中文翻译系列 (8) -----第二章 实体数据建模基础之继承关系映射TPT

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-8 Table per Type Inheritance 建模 问题 你有这样一 ...

  3. 《Entity Framework 6 Recipes》中文翻译系列 (10) -----第二章 实体数据建模基础之两实体间Is-a和Has-a关系建模、嵌入值映射

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-11 两实体间Is-a和Has-a关系建模 问题 你有两张有Is-a和Has-a ...

  4. 《Entity Framework 6 Recipes》翻译系列 (5) -----第二章 实体数据建模基础之有载荷和无载荷的多对多关系建模

    2-3 无载荷(with NO Payload)的多对多关系建模 问题 在数据库中,存在通过一张链接表来关联两张表的情况.链接表仅包含连接两张表形成多对多关系的外键,你需要把这两张多对多关系的表导入到 ...

  5. 《Entity Framework 6 Recipes》中文翻译系列 (9) -----第二章 实体数据建模基础之继承关系映射TPH

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-10 Table per Hierarchy Inheritance 建模 问题 ...

  6. 《Entity Framework 6 Recipes》中文翻译系列 (7) -----第二章 实体数据建模基础之拆分实体到多表以及拆分表到多实体

    2-6 拆分实体到多表 问题 你有两张或是更多的表,他们共享一样的主键,你想将他们映射到一个单独的实体. 解决方案 让我们用图2-15所示的两张表来演示这种情况. 图 2-15,两张表,Prodeuc ...

  7. 《Entity Framework 6 Recipes》中文翻译系列 (6) -----第二章 实体数据建模基础之使用Code First建模自引用关系

    2-5 使用Code First建模自引用关系 问题 你的数据库中一张自引用的表,你想使用Code First 将其建模成一个包含自关联的实体. 解决方案 我们假设你有如图2-14所示的数据库关系图的 ...

  8. 《Entity Framework 6 Recipes》中文翻译系列 目录篇 -持续更新

    为了方便大家的阅读和学习,也是响应网友的建议,在这里为这个系列做一个目录.在目录开始这前,我先来回答之前遇到的几个问题. 1.为什么要学习EF? 这个问题很简单,项目需要.这不像学校,没人强迫你学习! ...

  9. 《Entity Framework 6 Recipes》中文翻译 ---- 系列教程

    为了方便大家的阅读和学习,也是响应网友的建议,在这里为这个系列做一个目录.在目录开始这前,我先来回答之前遇到的几个问题. 1.为什么要学习EF? 这个问题很简单,项目需要.这不像学校,没人强迫你学习! ...

随机推荐

  1. 单独编译使用WebRTC的音频处理模块

    块,每块个点,(12*64=768采样)即AEC-PC仅能处理48ms的单声道16kHz延迟的数据,而 - 加载编译好的NS模块动态库 接下来只需要按照 此文 的描述在 android 的JAVA代码 ...

  2. 简单animate方法的封装

    function animate(ele,json,fn){ clearInterval(ele.timer); ele.timer = setInterval(function () { var b ...

  3. jq 剪切板

    文章链接 http://www.cnblogs.com/lkxsnow/p/5372665.html http://www.w3cfuns.com/notes/17735/020c2e68a60342 ...

  4. oracle(sql)基础篇系列(四)——数字字典、索引、序列、三范式

      数字字典表 --查看当前用户下面有哪些张表 select * from user_tables; select table_name from user_tables;   --查看当前用户下面有 ...

  5. Ruby Gem命令详解

    转自:http://www.jianshu.com/p/728184da1699 Gem介绍: Gem是一个管理Ruby库和程序的标准包,它通过Ruby Gem(如 http://rubygems.o ...

  6. pycharm快捷键、配置virtualenv环境,配置django调试,配置远程调试

    pycharm安装和首次使用 http://blog.csdn.net/chenggong2dm/article/details/9365437 快捷键: 找文件.代码.引用相关 1.双击shift ...

  7. PHPer不能不看的50个细节!

    1.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量, 单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的"函数&quo ...

  8. img只显示图片一部分 或 css设置背景图片只显示图片指定区域

    17:14 2016/3/22img只显示图片一部分 或 css设置背景图片只显示图片指定区域 background-position: 100% 56%; 设置背景图片显示图片的哪个坐标区域,图片左 ...

  9. JS中检测数据类型的几种方式及优缺点【转】

    1.typeof 用来检测数据类型的运算符 typeof value 返回值首先是一个字符串,其次里面包含了对应的数据类型,例如:"number"."string&quo ...

  10. 39个让你受益的HTML5教程

    1. 五分钟入门HTML5 (Learn HTML5 in 5 Minutes!) By Jennifer Marsman 毫无疑问,HTML5是一个热门话题.如果你需要一个迅速了解HTML基础的速成 ...