net基础篇entity framework 数据转换层通用类.docx

上传人:b****3 文档编号:3517362 上传时间:2022-11-23 格式:DOCX 页数:18 大小:20.25KB
下载 相关 举报
net基础篇entity framework 数据转换层通用类.docx_第1页
第1页 / 共18页
net基础篇entity framework 数据转换层通用类.docx_第2页
第2页 / 共18页
net基础篇entity framework 数据转换层通用类.docx_第3页
第3页 / 共18页
net基础篇entity framework 数据转换层通用类.docx_第4页
第4页 / 共18页
net基础篇entity framework 数据转换层通用类.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

net基础篇entity framework 数据转换层通用类.docx

《net基础篇entity framework 数据转换层通用类.docx》由会员分享,可在线阅读,更多相关《net基础篇entity framework 数据转换层通用类.docx(18页珍藏版)》请在冰豆网上搜索。

net基础篇entity framework 数据转换层通用类.docx

net基础篇entityframework数据转换层通用类

NET基础篇——EntityFramework数据转换层通用类

2012CSDN博客之星火热出炉!

2013年全国百所高校巡讲讲师招募

 

.NET基础篇——EntityFramework数据转换层通用类

分类:

EntityFramework2012-08-2709:

38221人阅读评论(0)收藏举报

在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行CRUD的操作,其中存在相当多的重复代码。

为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大家介绍一下EntityFramework时常用到的通用类。

首先在数据库建立起几个关联表:

Person、Company、Position,三个实体之间通过导航属性进行相互引用。

下面为大家分别介绍以泛型实现的Create、Read、Update、Delete操作:

1.Create

在ObjectContext类之中,早已经为大家预定了一个Create的操作AddObject:

voidObjectContext.AddObject(entitySetNamestring,objectentity)

voidObjectSet<T>.AddObject(Tentity)

1publicintAdd<T>(Tentity)whereT:

EntityObject

2{

3intchangedCount=0;

4try

5{

6using(BasicArchitectureEntitiescontext=newBasicArchitectureEntities())

7{

8context.AddObject(typeof(T).Name,entity);

9changedCount=context.SaveChanges();

10if(changedCount>0)

11context.AcceptAllChanges();

12}

13}

14catch(Exceptionex)

15{........}

16returnchangedCount;

17}

从下面的测试可以看到,ObjectContext.AddObject(entitySetNamestring,objectentity)已相当成熟,它不但可以加入单个实体,也可通过导航属性,一次性加入多个关联实体。

1staticvoidMain(string[]args)

2{

3BaseCommandcommand=newBaseCommand();

4//建立关联实体

5Companycompany=newCompany(){CompanyName="Sun"

6,Address="Beijing",Telephone="010-87654321"};

7Positionposition=newPosition(){PositionName="ProjectManager"

8,Salary=15000.00,Company=company};

9//通过Add<T>同时加入实体对象company与position

10intn=command.Add<Position>(position);

11

12Console.ReadKey();

13}

若要使用批量插入,只要在AddObject方法前多加一个重复语言即可,在此就不再多作解释了。

1publicintAddList<T>(List<T>entityList)whereT:

EntityObject

2{

3intchangedCount=0;

4try

5{

6using(BasicArchitectureEntitiescontext=newBasicArchitectureEntities())

7{

8foreach(TentityinentityList)

9context.AddObject(typeof(T).Name,entity);

10changedCount=context.SaveChanges();

11if(changedCount>0)

12context.AcceptAllChanges();

13}

14}

15catch(Exceptionex)

16{.......}

17returnchangedCount;

18}

2.Delete

同样地,ObjectContext类当中也存在方法ObjectContext.DeleteObject(objectentity)用于删除实体。

首先通过输入的参数id建立起EntityKey对象,然后在ObjectContext查找此实体,若实体存在则使用ObjectContext.DeleteObject(objectentity)方法把此实体删除。

1publicintDelete<T>(intid)whereT:

EntityObject

2{

3intchangedCount=0;

4try

5{

6using(BasicArchitectureEntitiescontext=newBasicArchitectureEntities())

7{

8//建立EntityKey对象

9EntityKeyentityKey=newEntityKey(

10"BasicArchitectureEntities."+typeof(T).Name,"Id",id);

11//通过EntityKey找到实体

12varobjResult=context.GetObjectByKey(entityKey);

13//若实体存在则删除实体

14if(objResult!

=null)

15context.DeleteObject(objResult);

16changedCount=context.SaveChanges();

17if(changedCount>0)

18context.AcceptAllChanges();

19}

20}

21catch(Exceptionex)

22{......}

23returnchangedCount;

24}

ObjectContext.DeleteObject(objectentity)与ObjectContext.AddObject(entitySetNamestring,objectentity)相同,可以通过导航属性,一次性删除多个关联实体。

但如果数据库中存在下面的数据

Company表:

Position表:

此时使用此intDelete<Company>

(2)方法删除Company对象,系统将会报错。

这是由于导航属性在默认情况下具有延时加载的特性,在系统使用ObjectContext.GetObjectByKey(entityKey)方法加载实体时,它的导航属性不会马上加载到上下文当中。

而是在调用该导航属性时,对象才会被加载。

因而系统通过ObjectContext.GetObjectByKey

(2)获取Company对象时,对应的Position对象并未被加载到上下文当中,所以当删除Company对象时,Position对象不能被同步删除,因而造成逻辑上的错误。

为解决这一问题,可以利用RelatedEnd.Load()方法提前加载导航属性。

RelatedEnd是EntityCollection<TEntity>、EntityReference的父类,它们是特定实体类型的对象集合,该实体类型表示一对多、多对一、多对多的关系。

而RelatedEnd.Load()方法,可以将一个或多个相关对象提前加载到相关实体当中。

首先通过ObjectContext.GetObjectByKey(entityKey)方法找到Company对象,然后利用反射属性PropertyInfo类获取导航属性Position,最后使用RelatedEnd.Load()方法,把导航属性加载到当前上下文中。

此时使用Delete<Company,Position>

(2)方法删除Company对象时,系统将能正常运行,并把对应的Position对象一并删除。

1publicintDelete<PKEntity,FKEntity>(intid)

2wherePKEntity:

EntityObject

3whereFKEntity:

EntityObject

4{

5intchangedCount=0;

6try

7{

8using(BasicArchitectureEntitiescontext=newBasicArchitectureEntities())

9{

10//根据软件Id建立EntityKey对象

11EntityKeyentityKey=newEntityKey(

12"BasicArchitectureEntities."+typeof(PKEntity).Name,"Id",id);

13//根据EntityKey查找对应对象

14PKEntityobjResult=context.GetObjectByKey(entityKey)asPKEntity;

15//根据FKEntity加载导航属性

16PropertyInfopropertyInfo=typeof(PKEntity).GetProperty(

17typeof(FKEntity).Name);

18EntityCollection<FKEntity>FKEntityList=propertyInfo.GetValue(

19objResult,null)asEntityCollection<FKEntity>;

20

21if(FKEntityList!

=null)

22FKEntityList.Load();

23

24if(objResult!

=null)

25context.DeleteObject(objResult);

26changedCount=context.SaveChanges();

27

28if(changedCount>0)

29context.AcceptAllChanges();

30}

31}

32catch(Exceptionex)

33{........}

34returnchangedCount;

35}

通过下面的方法也可根据输入的委托predicate,批量删除有关的数据。

1publicintDelete<T>(Func<T,bool>predicate)whereT:

EntityObject

2{

3intchangedCount=0;

4try

5{

6using(BasicArchitectureEntitiescontext=newBasicArchitectureEntities())

7{

8//根据输入的委托查找数据

9varlist=context.CreateObjectSet<T>().Where(predicate);

10//若存在数据,删除有关数据

11if(list.Count()>0)

12foreach(varobjinlist)

13context.DeleteObject(obj);

14

15changedCount=context.SaveChanges();

16if(changedCount>0)

17context.AcceptAllChanges();

18}

19}

20catch(Exceptionex)

21{......}

22returnchangedCount;

23}

与前面的例子相同,当使用Delete<Company>(x=>x.Id==2)方法删除Company对象时,由于导航属性Position处于延迟加载的状态,以致系统无法实现同步删除,从而令数据出现逻辑性的错误。

此时使用类似的方法,利用RelatedEnd.Load()把导航属性提前加入到上下文中,再删除Company对象时,系统就可以把对应Position对象一并删除。

1publicintDelete<PKEntity,FKEntity>(Func<PKEntity,bool>predicate)

2wherePKEntity:

EntityObject

3whereFKEntity:

EntityObject

4{

5intchangedCount=0;

6try

7{

8using(BasicArchitectureEntitiescontext=newBasicArchitectureEntities())

9{

10//根据输入的委托查找数据

11varlist=context.CreateObjectSet<PKEntity>().Where(predicate);

12//若数目大于0,删除有关数据

13if(list.Count()>0)

14{

15foreach(varobjinlist)

16{

17//在删除前加载其导航属性

18PropertyInfopropertyInfo=typeof(PKEntity)

19.GetProperty(typeof(FKEntity).Name);

20EntityCollection<FKEntity>FKEntityList=propertyInfo

21.GetValue(obj,null)asEntityCollection<FKEntity>;

22if(FKEntityList.Count>0)

23FKEntityList.Load();

24

25context.DeleteObject(obj);

26}

27}

28changedCount=context.SaveChanges();

29

30if(changedCount>0)

31context.AcceptAllChanges();

32}

33}

34catch(Exceptionex)

35{.......}

36returnchangedCount;

37}

此时使用Delete<Company,Position>(x=>x.Id==2),这样就可以把Company对象和相关的Position对象同时删除。

3.Update

ObjectContext中存在方法ObjectContext.ApplyCurrentValues<TEntity>和ObjectContext.ApplyOriginalValues<TEntity>,用于把将标量值从实体复制到ObjectContext中具有相同主键的对象集中。

注意:

在调用此方法前必须把实体预先加载到当前上下文当中,要不然系统将会显示“objectstatemanager无法跟踪具有相同键的多个对象”的错误。

由于DAL层的对象大部分使用单体模式进行开发,而BaseCommand是一个共用对象,在共同操作时,Create、Delete、Read等操作一般不会对实体造成逻辑性的影响。

但如果有多个实体同时调用Update操作,就有可能对实体造成逻辑性影响。

为了避免这一事件的发生,此处使用方法锁定的模式,以lock(object)锁定某一对象,以确保在同一时间内只会对一个实体进行更新。

首先通过反射方式获取对象的Id,然后通过ObjectContext.GetObjectByKey(entityKey)方法把实体加载到当前上下文当中,最后利用ObjectContext.ApplyCurrentValues<TEntity>方法,把新加入的实体的属性复制当前上下文。

1publicclassBaseCommand

2{

3privateobjecto=newobject();

4

5publicintUpdate<T>(Tentity)whereT:

EntityObject

6{

7lock(o)

8{

9intchangedCount=0;

10Typetype=typeof(T);

11

12try

13{

14using(BasicArchitectureEntitiescontext=newBasicArchitectureEntities())

15{

16//获取实体的Id属性

17PropertyInfoproperty=type.GetProperty("Id");

18objectid=property.GetValue(entity,null);

19//根据Id获取上下文中的对应实体

20EntityKeyentityKey=newEntityKey("BasicArchitectureEntities."

21+type.Name,"Id",id);

22varobjResult=context.GetObjectByKey(entityKey);

23//更新实体属性

24if(objResult!

=null)

25context.ApplyCurrentValues<T>(type.Name,entity);

26

27changedCount=context.SaveChanges();

28if(changedCount>0)

29context.AcceptAllChanges();

30}

31}

32catch(Exceptionex)

33{...}

34returnchangedCount;

35}

36}

37}

在一对多,多对一关系时,也可以使用以下方法进行导航属性的同步更新。

首先通过反射获取主实体的主键Id,然后建立EntityKey对象,再通过ObjectContext.GetObjectByKey(entityKey)方法在当前上下文当中获取此实体,最后通过ObjectContext.ApplyCurrentValues<TEntity>方法,把新加入的实体的属性复制当前上下文。

下一步就是对导航属性进行更新,首先通过反射获取外键属性,然后对一对多,多对一的关系进行分别处理。

在一对多关系时,把导航属性转换成EntityCollection<T2>对象集合,然后通过ObjectContext.ApplyCurrentValues<TEntity>方法对集合中的每个对象进行逐个更新。

在多对一关系时,直接把导航属性转换成T2类型的对象进行更新。

1publicintUpdate<T1,T2>(T1entity)

2whereT1:

EntityObject

3whereT2:

EntityObject

4{

5lock(o)

6{

7intchangedCount=0;

8TypetypeT1=typeof(T1);

9TypetypeT2=typeof(T2);

10try

11{

12using(BasicArchitectureEntitiescontext=newBasicArchitectureEntities())

13{

14PropertyInfoproperty=typeT1.GetProperty("Id");

15objectid=property.GetValue(entity,null);

16

17//根据软件Id建立EntityKey对象

18EntityKeyentityKey=newEntityKey("BasicArchitectureEntities."

19+typeT1.Name,"Id",id);

20//根据EntityKey查找对应对象

21T1objT1=context.GetObjectByKey(entityKey)asT1;

22//在上下文中更新当前对象

23if(objT1!

=null)

24context.ApplyCurrentValues<T1>(typeT1.Name,entity);

25

26//获取外键属性

27PropertyInfopropertyInfo=typeT1.GetProperty(typeT2.Name);

28

29//在一对多关键时更新导航属性

30varT2List=propertyInfo.GetValue(entity,null)

31asEntityCollection<T2>;

32if(T2List!

=null)

33{

34foreach(varobjinT2List.ToList())

35{

36varoldEntity=context.GetObjectByKey(obj.EntityKey);

37if(oldEntity!

=null)

38context.ApplyCurrentValues<T2>(typeT2.Name,obj);

39}

40}

41

42//在多对一,一对一关系时更新导航属性

43varobjT2=propertyInfo.Ge

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1