C#实体框架EF(entityframework)
⼀、什么是EntityFramework
微软官⽅提供的ORM⼯具,ORM让开发⼈员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上。EF提供变更跟踪、唯⼀性约束、惰性加载、查询事
物等。开发⼈员使⽤Linq语⾔,对数据库操作如同操作Object对象⼀样省事。
EF有三种使⽤场景,1.从数据库⽣成Class,2.由实体类⽣成数据库表结构,3.通过数据库可视化设计器设计数据库,同时⽣成实体类。
O/RM是什么?
ORM是将数据存储从域对象⾃动映射到关系型数据库的⼯具。ORM主要包括3个部分:域对象、关系数据库对象、映射关系。ORM使类提供⾃动化CRUD,使开发⼈
员从数据库API和SQL中解放出来。
⼆、EntityFramework架构
EDM(实体数据模型):EDM包括三个模型,概念模型、映射和存储模型。
概念模型︰概念模型包含模型类和它们之间的关系。独⽴于数据库表的设计。
存储模型︰存储模型是数据库设计模型,包括表、视图、存储的过程和他们的关系和键。
映射︰映射包含有关如何将概念模型映射到存储模型的信息。
LINQtoEntities︰LINQtoEntities是⼀种⽤于编写针对对象模型的查询的查询语⾔。它返回在概念模型中定义的实体。
EntitySQL:EntitySQL是另⼀种炉类似于L2E的⾔语,但相给L2E要复杂的多,所以开发⼈员不得不单独学习它。
ObjectServices(对象服务):是数据库的访问⼊⼝,负责数据具体化,从客户端实体数据到数据库记录以及从数据库记录和实体数据的转换。
EntityClientDataProvider:主要职责是将L2E或EntitySql转换成数据库可以识别的Sql查询语句,它使⽤通信向数据库发送数据可获取数据。
aProvider:使⽤标准的与数据库通信
三、EntityFramework运⾏环境
EF5由两部分组成,EFapi和framework4.0/4.5,⽽EF6是独⽴的,不依赖Framework。使⽤NuGet即可安装EF。
四、创建实体数据模型
使⽤向导创建实体类,或键添加,傻⽠式的~
添加完成之后,.config⽂件中会添加以下配置
<?xmlversion="1.0"?>
PublicKeyToken=b77a5c561934e089"requirePermission="fal"/>
connectionstring="datasource=.sqlexpress;initialcatalog=SchoolDB;integratedcurity=True;multipleactiveresultts=True;application
name=EntityFramework""providerName="Client"/>
Context&Entity类:
每个EntityDataModel⽣成⼀个context类,类数据库每个表⽣成⼀个entity类。如在中包含的两个重要的⽂件{EDMName}.和{EDMName}.tt:
:T4模板⽤于⽣成的context类,可以从⽬录结构中看到下包含⼀个⽂件。
:⽤于⽣成表映射的实体类。Entity类是POCO类。如Student⽣成
publicpartialclassStudent
{
publicStudent()
{
s=newHashSet
}
publicintStudentID{get;t;}
publicstringStudentName{get;t;}
publicNullable
publicbyte[]RowVersion{get;t;}
publicvirtualStandardStandard{get;t;}
publicvirtualStudentAddressStudentAddress{get;t;}
publicvirtualICollection
}
五、模板浏览器
以SchoolDB为例,切换到ModelView视图下,看到类图结构:
六、DBContext
第四节中提到EDM⽣成SchoolDBEntities类,该类从ext类继承。EntityFramework4.1中Context类从ObjectContext类继承。DbContext类
与ObjectContext类似,它对ObjcetContext类进⾏包装更利于开发的三种模式:CodeFirst、ModelFirst、DatabaFirst.
DbContext是EntityFramework很重要的部分,连接域模型与数据库的桥梁,是与数据库通信的主要类。
DbContext主要负责以下活动:
EntitySet::DbContext包含了所有映射到表的entities
Querying:将Linq-To-Entities转译为Sql并发送到数据库
ChangeTracking:从数据库获取entities后保留并跟踪实体数据变化
PersistingData:根据entity状态执⾏Inrt、update、delete命令
Caching:DbContext的默认第⼀级缓存,在上下⽂中的⽣命周期中存储entity
ManageRelationship:DbContext在DbFirst模式中使⽤CSDL、MSL、SSDL管理对象关系,Codefirst中使⽤fluentapi管理关系
ObjectMaterialization:DbContext将物理表转成entity实例对象
DEMO
DbContext实例化:
using(varctx=newSchoolDBEntities())
{
//CanperformCRUDoperationusingctxhere..
}
将DbContext转为ObjectContext
using(varctx=newSchoolDBEntities())
{
varobjectContext=(tContextAdapter).ObjectContext;
//uobjectContexthere..
}
七、EntityFramework中的Entity类型
POCOEntity(PlainOldCLRObject):
不依赖于任何Framework的类的类(alsoknownaspersistence-ignorantobjects),为EntityDataModel⽣成CRUD命令服务。
publicclassStudent
{
publicStudent()
{
s=newList
}
publicintStudentID{get;t;}
publicstringStudentName{get;t;}
publicNullable
publicStandardStandard{get;t;}
publicStudentAddressStudentAddress{get;t;}
publicIList
}
DynamicProxy(POCOProxy):
DynamicProxy是运⾏时POCO类的代理类,类似POCO类的包装。DynamicProxy允许延迟加载(Lazyloading),⾃动跟踪更改。POCOEntity必需满⾜以下⼏点才
能转为POCOProxy:
1.必需声明为public类
2.不可以是aled类
3.不可以是抽象类
4.导航属性必需是public,vitual(Entity包含两种属性,标量属性Scalarproperties:Entity本⾝的字段值,Navigationproperties:其它entity的引⽤如班级-学⽣)
5.集合属性必需是ICollection
reationEnabled选项必需是true
publicclassStudent
{
publicStudent()
{
s=newHashSet
}
publicintStudentID{get;t;}
publicstringStudentName{get;t;}
publicNullable
publicvirtualStandardStandard{get;t;}
publicvirtualStudentAddressStudentAddress{get;t;}
publicvirtualICollection
}
⼋、EntityRelationships:
九、EntityLifecycle
在我们做CRUD操作时,要先了解EntityFramework如何管理实体状态。每个实体的⽣命周期内都会在DbContext上下⽂中保存⼀个状态,分别是
AddedDeletedModifiedUnchangedDetached
⼗、CodeFirst、DBFirst、ModelFirst
CodeFirst领域设计时先定义实体类,⽤实体类⽣成数据库
DbFirst从数据库⽣成实体类
ModelFirst使⽤VisualStudio实体设计器,设计ER,同时⽣成Entity类和DB
⼗⼀、使⽤查询
三种查询⽅式1)LINQtoEntities,2)EntitySQL,and3)NativeSQL
LINQtoEntities:
LINQMethodsyntax:
//QueryingwithLINQtoEntities
using(varcontext=newSchoolDBEntities())
{
varL2EQuery=(s=>tName=="Bill");
varstudent=rDefault
}
LINQQuerysyntax:
using(varcontext=newSchoolDBEntities())
{
varL2EQuery=ts
tName=="Bill"lectst;
varstudent=rDefault
}
EntitySQL:
//QueryingwithObjectServicesandEntitySQL
stringsqlString="ts"+
"tName=='Bill'";
varobjctx=(ctxasIObjectContextAdapter).ObjectContext;
ObjectQuery
StudentnewStudent=
//使⽤EntityDataReader
using(varcon=newEntityConnection("name=SchoolDBEntities"))
{
();
EntityCommandcmd=Command();
dText="tName='Bill'";
Dictionary
using(EntityDataReaderrdr=eReader(tialAccess|onnection))
{
while(())
{
inta=32(0);
varb=ing(1);
(a,b);
}
}
}
NativeSQL:
using(varctx=newSchoolDBEntities())
{
varstudentName=ry("Selectstudentid,studentname,standardIdfromStudentwherestudentname='Bill'").FirstOrDefault
}
⼗⼆、跟踪变更与持久化场景
在连接状态下持久化与脱机状态下持久化
连机状态下持久化,在同⼀个DbContext中不需要销毁Entity,直接写⼊数据库
脱机状态持久化指读取和保存Entity在两个不同的DbContext中,Context2不知道Entity的更新状态,所以必需通知Context2当前的Entity做了何种更新。
Context只在DbSet上跟踪添加和删除
正确的添加和删除
using(varcontext=newSchoolDBEntities())
{
varstudentList=
//Performcreateoperation
(newStudent(){StudentName="NewStudent"});
//PerformUpdateoperationStudentstudentToUpdate=(s=>tName=="student1").FirstOrDefault
tName="Editedstudent1";
//Performdeleteoperation
(tAt
//ExecuteInr,Update&Deletequeriesinthedataba
anges();
}
以下代码在List中添加和删除不起作⽤,只有更⽣有效
using(varcontext=newSchoolDBEntities())
{
varstudentList=
//Addstudentinlist
(newStudent(){StudentName="NewStudent"});
//PerformupdateoperationStudentstudentToUpdate=(s=>tName=="Student1").FirstOrDefault
tName="Editedstudent1";
//Deletestudentfromlistif(>0)
(tAt
//SaveChangeswillonlydoupdateoperationnotaddanddelete
anges();
}
脱机实体
脱机实体管理要先附加到Context
//disconnectedentitygraphStudentdisconnectedStudent=newStudent(){StudentName="NewStudent"};
tAddress=newStudentAddress(){Address1="Address",City="City1"};
using(varctx=newSchoolDBEntities())
{
//attachdisconnectedStudententitygraphtonewcontextinstance-ctx
(disconnectedStudent);
//getDbEntityEntryinstancetochecktheEntityStateofspecifiedentity
varstudentEntry=(disconnectedStudent);
varaddressEntry=(tAddress);
ine("StudentEntityState:{0}",);
ine("StudentAddressEntityState:{0}",);
}
添加多个关系实体时与添加单个实体⼀样,更新关系实体时需要跟踪每个实体的状态。
⼗三EntityFramework并发处理
添加RowVersion,类型为TimeStamp字段,在EDM中X修改并发属性为Fixed。EF更新实体时会先检查RowVersion,如果发现RowVersion不⼀致,则抛出
DbUpdateConcurrencyException异常
⼗四贪婪加载、惰性加载与定向加载
贪婪加载:使⽤Include(),⾃动加载关联实体
using(varcontext=newSchoolDBEntities())
{
varres=(e("Standard")
tName=="Student1"
lects).FirstOrDefault
}
执⾏Sql
SELECTTOP(1)
[Extent1].[StudentID]AS[StudentID],
[Extent1].[StudentName]AS[StudentName],
[Extent2].[StandardId]AS[StandardId],
[Extent2].[StandardName]AS[StandardName],
[Extent2].[Description]AS[Description]
FROM[dbo].[Student]AS[Extent1]
LEFTOUTERJOIN[dbo].[Standard]AS[Extent2]ON[Extent1].[StandardId]=[Extent2].[StandardId]
WHERE'Student1'=[Extent1].[StudentName]
惰性加载:延迟加载对象关联的实体,⽤到时再加载,EF默认为LazyLoading
using(varctx=newSchoolDBEntities())
{
//LoadingstudentsonlyIList
Studentstd=studList[0];
//LoadsStudentaddressforparticularStudentonly(perateSQLquery)
StudentAddressadd=tAddress;
}
定向加载:Reference()和Collection()⽅法
using(varcontext=newSchoolDBEntities())
{
//Loadingstudentsonly
IList
Studentstd=(s=>tID==1).FirstOrDefault
//LoadsStandardforparticularStudentonly(perateSQLquery)
(std).Reference(s=>rd).Load();
//LoadsCoursforparticularStudentonly(perateSQLquery)
(std).Collection(s=>s).Load();
}
⼗五:执⾏SQL
返回实体
using(varctx=newSchoolDBEntities())
{
//列名必需要Entity属性匹配
varstudentList=ry("Select*fromStudent").ToList
}
返回⾮实体类型
using(varctx=newSchoolDBEntities())
{
//GetstudentnameofstringtypestringstudentName=ry
fromStudentwherestudentid=1").FirstOrDefault
}
执⾏SQL命令
using(varctx=newSchoolDBEntities())
{
//UpdatecommandintnoOfRowUpdated=eSqlCommand("Updatestudent
tstudentname='changedstudentbycommand'wherestudentid=1");
//InrtcommandintnoOfRowInrted=eSqlCommand("inrtintostudent(studentname)
values('NewStudent')");
//DeletecommandintnoOfRowDeleted=eSqlCommand("deletefromstudent
wherestudentid=1");
}
本文发布于:2022-11-24 18:14:35,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/13430.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |