04 第四讲 ADONET实体框架.docx
- 文档编号:10639620
- 上传时间:2023-02-22
- 格式:DOCX
- 页数:19
- 大小:40.37KB
04 第四讲 ADONET实体框架.docx
《04 第四讲 ADONET实体框架.docx》由会员分享,可在线阅读,更多相关《04 第四讲 ADONET实体框架.docx(19页珍藏版)》请在冰豆网上搜索。
04第四讲ADONET实体框架
第四讲ADO.NET实体框架
长久以来,程序员和数据库总是保持着一种微妙的关系,在商用应用程序中,数据库一定是不可或缺的元件,这让程序员一定要为了连接与访问数据库而去学习SQL语句,然而在众多设计工具中,数据以对象的形式体现。
因此在业界中有很多人都在研究如何将对象模型和数据库集成在一起,对象关系对应(Object-RelationalMapping)的技术就是由此而生,像Hibernate或NHibernate都是这个技术下的产物,而微软虽然有了ADO.NET这个数据访问的利器,但却没有像NHibernate这样的对象对应工具,因此微软在.NETFramework2.0发展时期,就提出了一个ObjectSpace的概念,ObjectSpace可以让应用程序可以用完全对象化的方法连接与访问数据库,其技术概念与NHibernate相当类似,然而ObjectSpace工程相当大,在.NETFramework2.0完成时仍无法全部完成,因此微软将ObjectSpace纳入下一版本的.NETFramework中,并且再加上一个设计的工具(Designer),构成了现在的ADO.NETEntityFramework。
EntityFramework利用了抽象化数据结构的方式,将每个数据库对象都转换成应用程序对象(entity),而数据字段都转换为属性(property),关系则转换为结合属性(association),让数据库的E/R模型完全的转成对象模型,如此让程序设计师能用最熟悉的编程语言来调用访问。
而在抽象化的结构之下,则是高度集成与对应结构的概念层、对应层和储存层,以及支持EntityFramework的数据提供者(provider),让数据访问的工作得以顺利与完整的进行。
4.1为概念模型赋予生命
数据建模的一种由来已久且常见的设计模式是将数据模型分为三个部分:
概念模型、逻辑模型和物理模型。
概念模型定义要建模的系统中的实体和关系。
关系数据库的逻辑模型通过外键约束将实体和关系规范化到表中。
物理模型通过指定分区和索引等存储详细信息实现特定数据引擎的功能。
物理模型由数据库管理员进行优化以改善性能,而编写应用程序代码的程序员的工作主要限制为通过编写SQL查询和调用存储过程来处理逻辑模型。
概念模型通常用作捕获和传达应用程序的要求的工具,常常以静态关系图的形式供项目早期阶段查看和讨论,随后被弃用。
许多开发团队会跳过概念模型的创建,直接从指定关系数据库中的表、列和键开始工作。
实体框架,可使开发人员查询概念模型中的实体和关系,同时依赖于实体框架将这些操作转换为特定于数据源的命令,从而为概念模型赋予生命。
这使应用程序不再对特定数据源具有硬编码的依赖性。
概念模型、存储模型以及两个模型之间的映射以外部规范(称为实体数据模型(EDM))表示。
可以根据需要对存储模型和映射进行更改,而不需要对概念模型、数据类或应用程序代码进行更改。
存储模型是特定于提供程序的,因此可以在各种数据源之间使用一致的概念模型。
EDM由以下三种模型和具有相应文件扩展名的映射文件进行定义。
●概念架构定义语言文件(.csdl)--定义概念模型。
●存储架构定义语言文件(.ssdl)--定义存储模型(又称逻辑模型)。
●映射规范语言文件(.msl)--定义存储模型与概念模型之间的映射。
实体框架使用这些基于XML的模型和映射文件将对概念模型中的实体和关系的创建、读取、更新和删除操作转换为数据源中的等效操作。
EDM甚至支持将概念模型中的实体映射到数据源中的存储过程。
4.2将对象映射到数据
面向对象的编程对与数据存储系统的交互提出了一个难题。
虽然类的组织通常可比较接近地反映出关系数据库表的组织,但是拟合程度并不完美。
多个规范化表通常对应于单个类,类之间的关系并未按照表之间的关系一样表示。
例如,若要表示某个销售订单的客户,一个Order类可使用包含对Customer类实例的引用的属性,但是数据库中的一个Order表行包含的一个外键列(或列集)具有对应于Customer表中的主键值的值。
一个Customer类可以具有名为Orders的属性,该属性包含Order类的实例的集合,但是数据库中的Customer表不包含相应的列。
现有解决方案只能通过将面向对象的类和属性映射到关系表和列来尝试弥合这种通常称为“阻抗不匹配”的差异。
实体框架没有采用这种传统方法,而是将逻辑模型中的关系表、列和外键约束映射到概念模型中的实体和关系。
这在定义对象和优化逻辑模型方面都增加了灵活性。
实体数据模型工具基于概念模型生成可扩展数据类。
这些类是分部类,可以通过开发人员添加的其他成员进行扩展。
为特定概念模型生成的类派生自一些基类,这些基类提供对象服务以将实体具体化为对象以及跟踪和保存更改。
开发人员可以使用这些生成的类以由导航属性关联起来的对象的形式来处理实体和关系。
4.3访问和更改实体数据
实体框架不仅仅是另一种对象关系映射解决方案,还从根本上使应用程序可以访问和更改表示为概念模型中的实体和关系的数据。
对象服务使用EDM将对概念模型中所表示的实体类型的对象查询转换为特定于数据源的查询。
查询结果具体化为对象服务管理的对象。
实体框架提供以下方式用于查询EDM并返回对象:
●LINQtoEntities--提供语言集成查询(LINQ)支持用于查询在概念模型中定义的实体类型。
●EntitySQL--与存储无关的SQL方言,直接使用概念模型中的实体并支持诸如继承和关系等EDM功能。
EntitySQL可用于对象查询和使用EntityClient提供程序执行的查询。
●查询生成器方法--可以使用LINQ风格的查询方法构造EntitySQL查询。
实体框架中包含EntityClient数据提供程序。
此提供程序管理连接,将实体查询转换为特定于数据源的查询,并返回一个由对象服务用来将实体数据具体化为对象的数据读取器。
当不需要对象具体化时,通过使应用程序执行EntitySQL查询并使用返回的只读数据读取器,还可以像标准ADO.NET数据提供程序一样使用EntityClient提供程序。
下图说明实体框架的使用过程:
实体框架生成一个从ObjectContext派生的类,该类表示概念模型中的实体容器。
此对象上下文提供跟踪更改以及管理标识、并发和关系的功能。
此类还公开将插入、更新和删除操作写入数据源的SaveChanges方法。
与查询类似,这些更改是由系统自动生成的命令或由开发人员指定的存储过程执行的。
下面通过一个示例来说明实体数据框架的使用。
一、创建School数据库和架构
1.在“文件”菜单上,指向“新建”,然后单击“数据库引擎查询”。
2.在“连接到数据库引擎”对话框中,键入localhost或本地SQLServer实例的名称,然后单击“连接”。
3.在查询窗口中粘贴以下Transact-SQL脚本,然后单击“执行”。
(数据库脚本见附件)
二、创建CourseManager应用程序
1.在“文件”菜单上单击“新建项目”。
2.在“项目类型”窗格中,选择“VisualBasic”或“VisualC#”。
3.在“模板”窗格中,选择“Windows窗体应用程序”。
4.对于项目名称输入CourseManager,然后单击“确定”。
5.在CourseManager项目中,选择默认窗体(Form1)。
6.在“文件属性”窗格中,将“文件名”更改为CourseViewer.vb或CourseViewer.cs。
7.在“解决方案资源管理器”中,双击CourseViewer.vb或CourseViewer.cs以打开窗体。
8.在“属性”窗格中,将Name属性更改为CourseViewer,并将Text属性更改为CourseViewer。
9.在“工具箱”中,展开“公共控件”,将“复合框”控件拖到窗体上,然后将该控件的名称更改为departmentList。
10.在“工具箱”中,将“按钮”控件拖到窗体上,将此控件的名称更改为closeForm,并将Text值更改为Close。
11.在“工具箱”中,展开“数据”,将“DataGridView”控件拖到窗体上,然后将该控件的名称更改为courseGridView。
12.双击closeForm按钮控件。
13.此时将打开窗体的代码页并创建closeForm_Click事件处理程序方法。
14.在closeForm_Click事件处理程序方法中,键入以下用于关闭窗体的代码:
//Closetheform.
this.Close();
三、生成School实体数据模型
1.在“解决方案资源管理器”中选择CourseManager项目,右键单击,指向“添加”,然后单击“新建项”。
2.在“模板”窗格中,选择“ADO.NET实体数据模型”。
3.为模型名称键入School.edmx,然后单击“添加”。
4.将显示“实体数据模型向导”的开始页。
5.在“选择模型内容”对话框中,选择“从数据库生成”。
然后,单击“下一步”。
6.单击“新建连接”按钮。
7.在“选择数据源”对话框中,选择您的数据源,然后单击“继续”。
8.在“连接属性”对话框中,输入服务器名称,选择身份验证方法,对于数据库名称,键入School,然后单击“确定”。
9.将使用您的数据库连接设置更新“选择您的数据连接”对话框。
10.确保选中“将App.Config中的实体连接设置保存为:
”,并且值设置为SchoolEntities。
然后,单击“下一步”。
11.将显示“选择数据库对象”对话框。
12.确保选中所有表和存储过程,且“模型命名空间”的值为SchoolModel,然后单击“完成”以完成向导。
13.在“解决方案资源管理器”中,双击School.edmx文件。
此时将在“ADO.NET实体数据模型设计器”窗口中显示School模型。
四、查询实体和关联
●在School数据库中查询系
1.在CourseViewer窗体的代码文件的开始处,添加以下using(C#)或Imports(VisualBasic)语句,以引用从School数据库和实体命名空间中创建的模型。
usingSystem.Data.Objects;
usingSystem.Data.Objects.DataClasses;
2.在CourseViewer窗体的分部类定义的顶部,添加以下用于创建ObjectContext实例的代码。
//CreateanObjectContextinstancebasedonSchoolEntity.
privateSchoolEntitiesschoolContext;
3.在CourseViewer窗体设计器中,双击CourseViewer窗体。
此时将打开窗体的代码页并创建courseViewer_Load事件处理程序方法。
4.在courseViewer_Load事件处理程序方法中,复制并粘贴以下用于定义DataGridView的代码,执行返回系科集合的查询(按Name排序),然后将Department对象的集合绑定到departmentList控件。
//InitializetheObjectContext.
schoolContext=newSchoolEntities();
//DefineaquerythatreturnsallDepartmentobjectsandrelated
//Courseobjects,orderedbyname.
//查询生成器方法
ObjectQuery
schoolContext.Department.Include("Course").OrderBy("it.Name");
//***特别注意include的用法,后面的课程中将详细介绍***
//LINQtoEntities语法
vardepartmentQuery1=fromdepartmentinschoolContext.Department.Include("Course")
orderbydepartment.Name
selectdepartment;
try{
//BindtheComboBoxcontroltothequery,whichis
//executedduringdatabinding.
this.departmentList.DataSource=departmentQuery1;
this.departmentList.DisplayMember="Name";
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}
●显示所选系的课程
1.在CourseViewer窗体设计器中,双击departmentList控件。
此时将创建departmentList_SelectedIndexChanged事件处理程序方法。
2.粘贴以下用于加载与所选系相关的课程的代码。
try
{
//Gettheobjectfortheselecteddepartment.
Departmentdepartment=
(Department)this.departmentList.SelectedItem;
//BindthegridviewtothecollectionofCourseobjects
//thatarerelatedtotheselectedDepartmentobject.
courseGridView.DataSource=department.Course;courseGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}
五、插入和更新数据
●保存对对象所做的更改
1.在“工具箱”中,展开“公共控件”,将“按钮”控件拖到CourseViewer窗体设计器,将控件的名称更改为saveChanges,并将Text值更改为Update。
2.在CourseViewer窗体设计器中,双击saveChanges控件。
3.此时将创建saveChanges_Click事件处理程序方法。
4.粘贴以下代码,这些代码将对象更改保存到数据库中。
try
{
intnumChanges;
//Saveobjectchangestothedatabase,displayamessage,
//andrefreshtheform.
numChanges=schoolContext.SaveChanges();
MessageBox.Show(numChanges.ToString()+
"change(s)savedtothedatabase.");
this.Refresh();
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}
●通过释放长时间运行的对象上下文关闭连接
在closeForm_Click事件处理程序方法中,键入以下代码。
此代码在关闭窗体之前释放对象上下文。
//Disposetheobjectcontext.
schoolContext.Dispose();
4.4对象服务
对象服务是实体框架的一个组件,您可使用它来查询、插入、更新和删除数据,它表示为作为实体类型实例的强类型CLR对象。
对象服务支持针对实体数据模型(EDM)中定义的类型进行的语言集成查询(LINQ)和EntitySQL查询。
对象服务将返回的数据具体化为对象,并将对象更改传播回数据源。
它还提供了跟踪更改、将对象绑定到控件以及处理并发问题的功能。
对象服务由System.Data.Objects和System.Data.Objects.DataClasses命名空间中的类来实现。
●对象上下文
ObjectContext类是以对象(这些对象是EDM中定义的实体类型的实例)的形式与数据进行交互的主要类。
ObjectContext类的实例封装以下内容:
●到数据库的连接,以EntityConnection对象的形式封装。
●描述模型的元数据,以MetadataWorkspace对象的形式封装。
●在创建、更新和删除操作过程中跟踪对象的ObjectStateManager对象。
本讲重点描述如何利用对象服务完成对象的添加、修改、删除及并发控制,至于如何利用对象服务完成查询,我们放在下一讲。
对象上下文中的对象是实体类型的实例,表示数据源中的数据。
在对象上下文中可以修改、创建和删除对象,对象服务会跟踪对这些对象所做的更改。
调用SaveChanges方法时,对象服务会生成并执行一些命令,这些命令将对数据源执行等效的插入、更新或删除语句。
下面的程序基于AdventureWorks销售实体数据模型,请按以下步骤创建。
1.在“项目”菜单上单击“添加新项”。
2.在“模板”窗格中,选择“ADO.NET实体数据模型”。
3.键入AdventureWorks.edmx作为模型名称,然后单击“添加”。
将显示“实体数据模型向导”的第一页。
4.在“选择模型内容”对话框中,选择“从数据库生成”。
然后,单击“下一步”。
5.单击“新建连接”按钮。
6.在“连接属性”对话框中,键入服务器名称,选择身份验证方法,对于数据库名称,键入AdventureWorks,然后单击“确定”。
“选择您的数据连接”对话框将以您的数据库连接设置更新。
7.确保“将App.Config中的实体连接设置另存为:
”复选框已选中,并且其值设置为AdventureWorksEntities。
然后,单击“下一步”。
8.在“选择数据库对象”对话框中,清除所有对象,展开“表”,然后选择以下表对象:
●Address
●Contact
●Product
●SalesOrderHeader
●SalesOrderDetail
9.单击“完成”以完成向导。
4.4.1添加、删除、修改对象
在本示例中,对象查询根据指定的SalesOrderID返回单个SalesOrderHeader对象。
此订单的状态从5(已发货)更改为1(在制品),向订单中添加一个新项,并删除第一个现有项。
将调用SaveChanges方法以将更改写到数据库中。
然后,将订单的结果状态写到控制台。
//Specifytheordertoupdate.
intorderId=43680;
using(AdventureWorksEntitiescontext=newAdventureWorksEntities())
{
try
{
SalesOrderHeaderorder=(fromohincontext.SalesOrderHeader
whereoh.SalesOrderID==orderIdselectoh).First();
//Changethestatusandshipdateofanexistingorder.
order.Status=1;
order.ShipDate=DateTime.Today;
//Loaditemsfortheorder,ifnotalreadyloaded.
//显式加载和SalesOrderHeader对象相关的SalesOrderDetail对象,两者的关系//为1对多的关系
if(!
order.SalesOrderDetail.IsLoaded)
{
order.SalesOrderDetail.Load();
}
//Deletethefirstitemintheorder.
context.DeleteObject(order.SalesOrderDetail.First());
//CreateanewitemusingthestaticCreatemethod
//andaddittotheorder.
//实体框架工具使用概念性架构定义语言(CSDL)文件以生成用于定义对象//层的代码。
当生成数据类时,将使用静态create工厂方法生成每个类。
此//方法用于实例化对象并设置此类的不能为空的所有属性。
此方法对于在CSDL//文件中已应用Nullable="false"属性(Attribute)的每个属
//(Property)都具有一个参数。
当创建具有许多必需属性的对象时使用此方法。
order.SalesOrderDetail.Add(
SalesOrderDetail.CreateSalesOrderDetail(0,
0,2,750,1,(decimal)2171.2942,0,0,
Guid.NewGuid(),DateTime.Today));
//Savechangesintheobjectcontexttothedatabase.
intchanges=context.SaveChanges();
Console.WriteLine(changes.ToString()+"changessaved!
");
Console.WriteLine("Updateditemfororder:
"
+order.SalesOrderID.ToString());
foreach(SalesOrderDetailitemin
order.SalesOrderDetail.OrderBy(od=>od.SalesOrderDetailID))
{
Console.WriteLine("ItemID:
"
+item.SalesOrderDetailID.ToString()+"Product:
"
+item.ProductID.ToString()+"Quantity:
"
+item.OrderQty.ToString());
}
}
catch(UpdateExceptione
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 04 第四讲 ADONET实体框架 第四 ADONET 实体 框架