首页 ADO.NET EF 资料

ADO.NET EF 资料

举报
开通vip

ADO.NET EF 资料 在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行 CRUD 的操作,其中存在相当 多的重复代码。为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大 家介绍一下 Entity Framework 时常用到的通用类。 首先在数据库建立起几个关联表:Person、Company、Position,三个实体之间通过导航属性进行相 互引用。 下面为大家分别介绍以泛型实现的 Create、Read、Update、Delete 操作: 1. Create 在 ObjectContext...

ADO.NET EF 资料
在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行 CRUD 的操作,其中存在相当 多的重复代码。为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大 家介绍一下 Entity Framework 时常用到的通用类。 首先在数据库建立起几个关联 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf :Person、Company、Position,三个实体之间通过导航属性进行相 互引用。 下面为大家分别介绍以泛型实现的 Create、Read、Update、Delete 操作: 1. Create 在 ObjectContext 类之中,早已经为大家预定了一个 Create 的操作 AddObject: void ObjectContext.AddObject(entitySetName string,object entity) void ObjectSet.AddObject(T entity) 1 public int Add(T entity) where T : EntityObject 2 { 3 int changedCount = 0; 4 try 5 { 6 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 7 { 8 context.AddObject(typeof(T).Name, entity); 9 changedCount = context.SaveChanges(); 10 if (changedCount > 0) 11 context.AcceptAllChanges(); 12 } 13 } 14 catch (Exception ex) 15 { ........ } 16 return changedCount; 17 } 从下面的测试可以看到,ObjectContext.AddObject(entitySetName string,object entity)已相当成熟, 它不但可以加入单个实体,也可通过导航属性,一次性加入多个关联实体。 1 static void Main(string[] args) 2 { 3 BaseCommand command = new BaseCommand(); 4 //建立关联实体 5 Company company = new Company() { CompanyName = "Sun" 6 ,Address="Beijing",Telephone="010-87654321"}; 7 Position position = new Position() { PositionName = "Project Manager" 8 , Salary = 15000.00, Company = company }; 9 //通过 Add同时加入实体对象 company与 position 10 int n=command.Add(position); 11 12 Console.ReadKey(); 13 } 若要使用批量插入,只要在 AddObject 方法前多加一个重复语言即可,在此就不再多作解释了。 1 public int AddList(List entityList) where T : EntityObject 2 { 3 int changedCount = 0; 4 try 5 { 6 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 7 { 8 foreach (T entity in entityList) 9 context.AddObject(typeof(T).Name, entity); 10 changedCount = context.SaveChanges(); 11 if (changedCount > 0) 12 context.AcceptAllChanges(); 13 } 14 } 15 catch (Exception ex) 16 { ....... } 17 return changedCount; 18 } 2. Delete 同样地,ObjectContext 类当中也存在方法 ObjectContext.DeleteObject(object entity)用于删除实体。 首先通过输入的参数 id 建立起 EntityKey 对象,然后在 ObjectContext 查找此实体,若实体存在则使 用 ObjectContext.DeleteObject(object entity)方法把此实体删除 。 1 public int Delete(int id) where T : EntityObject 2 { 3 int changedCount = 0; 4 try 5 { 6 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 7 { 8 //建立 EntityKey对象 9 EntityKey entityKey = new EntityKey( 10 "BasicArchitectureEntities." + typeof(T).Name, "Id", id); 11 //通过 EntityKey找到实体 12 var objResult = context.GetObjectByKey(entityKey); 13 //若实体存在则删除实体 14 if (objResult != null) 15 context.DeleteObject(objResult); 16 changedCount = context.SaveChanges(); 17 if (changedCount > 0) 18 context.AcceptAllChanges(); 19 } 20 } 21 catch (Exception ex) 22 { ...... } 23 return changedCount; 24 } ObjectContext.DeleteObject(object entity)与 ObjectContext.AddObject(entitySetName string,object entity)相同,可以通过导航属性,一次性删除多个关联实体。但如果数据库中存在下面的数据 Company 表: Position 表: 此时使用此 int Delete(2) 方法删除 Company 对象,系统将会报错。这是由于导航属性 在默认情况下具有延时加载的特性,在系统使用 ObjectContext.GetObjectByKey(entityKey)方法加载 实体时,它的导航属性不会马上加载到上下文当中。而是在调用该导航属性时,对象才会被加载。 因而系统通过 ObjectContext.GetObjectByKey(2)获取 Company 对象时,对应的 Position 对象并未被加 载到上下文当中,所以当删除 Company 对象时,Position 对象不能被同步删除,因而造成逻辑上的 错误。为解决这一问题,可以利用 RelatedEnd.Load()方法提前加载导航属性。 RelatedEnd 是 EntityCollection 、EntityReference 的父类,它们是特定实体类型的对象集合, 该实体类型表示一对多、多对一、多对多的关系。而 RelatedEnd.Load()方法,可以将一个或多个 相关对象提前加载到相关实体当中。 首先通过 ObjectContext.GetObjectByKey(entityKey)方法找到 Company 对象,然后利用反射属性 PropertyInfo 类获取导航属性 Position,最后使用 RelatedEnd.Load()方法,把导航属性加载到当前 上下文中。此时使用 Delete(2)方法删除 Company 对象时,系统将能正常运行, 并把对应的 Position 对象一并删除。 1 public int Delete(int id) 2 where PKEntity : EntityObject 3 where FKEntity : EntityObject 4 { 5 int changedCount = 0; 6 try 7 { 8 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 9 { 10 //根据软件 Id建立 EntityKey对象 11 EntityKey entityKey = new EntityKey( 12 "BasicArchitectureEntities." + typeof(PKEntity).Name, "Id", id); 13 //根据 EntityKey查找对应对象 14 PKEntity objResult = context.GetObjectByKey(entityKey) as PKEntity; 15 //根据 FKEntity加载导航属性 16 PropertyInfo propertyInfo = typeof(PKEntity).GetProperty( 17 typeof(FKEntity).Name); 18 EntityCollection FKEntityList = propertyInfo.GetValue( 19 objResult, null) as EntityCollection; 20 21 if (FKEntityList != null) 22 FKEntityList.Load(); 23 24 if (objResult != null) 25 context.DeleteObject(objResult); 26 changedCount = context.SaveChanges(); 27 28 if (changedCount > 0) 29 context.AcceptAllChanges(); 30 } 31 } 32 catch (Exception ex) 33 { ........ } 34 return changedCount; 35 } 通过下面的方法也可根据输入的委托 predicate,批量删除有关的数据。 1 public int Delete(Func predicate) where T: EntityObject 2 { 3 int changedCount = 0; 4 try 5 { 6 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 7 { 8 //根据输入的委托查找数据 9 var list = context.CreateObjectSet().Where(predicate); 10 //若存在数据,删除有关数据 11 if (list.Count() > 0) 12 foreach (var obj in list) 13 context.DeleteObject(obj); 14 15 changedCount = context.SaveChanges(); 16 if (changedCount > 0) 17 context.AcceptAllChanges(); 18 } 19 } 20 catch (Exception ex) 21 { ...... } 22 return changedCount; 23 } 与前面的例子相同,当使用 Delete(x=>x.Id==2) 方法删除 Company 对象时,由于导航属 性 Position 处于延迟加载的状态,以致系统无法实现同步删除,从而令数据出现逻辑性的错误。 此时使用类似的方法,利用 RelatedEnd.Load() 把导航属性提前加入到上下文中,再删除 Company 对象时,系统就可以把对应 Position 对象一并删除。 1 public int Delete(Func predicate) 2 where PKEntity : EntityObject 3 where FKEntity : EntityObject 4 { 5 int changedCount = 0; 6 try 7 { 8 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 9 { 10 //根据输入的委托查找数据 11 var list = context.CreateObjectSet().Where(predicate); 12 //若数目大于 0,删除有关数据 13 if (list.Count() > 0) 14 { 15 foreach (var obj in list) 16 { 17 //在删除前加载其导航属性 18 PropertyInfo propertyInfo = typeof(PKEntity) 19 .GetProperty(typeof(FKEntity).Name); 20 EntityCollection FKEntityList = propertyInfo 21 .GetValue(obj, null) as EntityCollection; 22 if (FKEntityList.Count > 0) 23 FKEntityList.Load(); 24 25 context.DeleteObject(obj); 26 } 27 } 28 changedCount = context.SaveChanges(); 29 30 if (changedCount > 0) 31 context.AcceptAllChanges(); 32 } 33 } 34 catch (Exception ex) 35 { ....... } 36 return changedCount; 37 } 此时使用 Delete(x=>x.Id==2),这样就可以把 Company 对象和相关的 Position 对 象同时删除。 3. Update ObjectContext 中存在方法 ObjectContext.ApplyCurrentValues 和 ObjectContext.ApplyOriginalValues,用于把将标量值从实体复制到 ObjectContext 中具有相 同主键的对象集中。 注意:在调用此方法前必须把实体预先加载到当前上下文当中,要不然系统将会显示 “objectstatemanager 无法跟踪具有相同键的多个对象” 的错误。 由于 DAL 层的对象大部分使用单体模式进行开发,而 BaseCommand 是一个共用对象,在共同 操作时,Create、Delete、Read 等操作一般不会对实体造成逻辑性的影响。但如果有多个实体 同时调用 Update 操作,就有可能对实体造成逻辑性影响。为了避免这一事件的发生,此处使 用方法锁定的模式,以 lock(object) 锁定某一对象,以确保在同一时间内只会对一个实体进行 更新。 首先通过反射方式获取对象的 Id,然后通过 ObjectContext.GetObjectByKey(entityKey) 方法把 实体加载到当前上下文当中,最后利用 ObjectContext.ApplyCurrentValues 方法,把新 加入的实体的属性复制当前上下文。 1 public class BaseCommand 2 { 3 private object o = new object(); 4 5 public int Update(T entity) where T : EntityObject 6 { 7 lock (o) 8 { 9 int changedCount = 0; 10 Type type = typeof(T); 11 12 try 13 { 14 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 15 { 16 //获取实体的 Id属性 17 PropertyInfo property = type.GetProperty("Id"); 18 object id = property.GetValue(entity, null); 19 //根据 Id获取上下文中的对应实体 20 EntityKey entityKey = new EntityKey("BasicArchitectureEntities." 21 + type.Name, "Id", id); 22 var objResult = context.GetObjectByKey(entityKey); 23 //更新实体属性 24 if (objResult != null) 25 context.ApplyCurrentValues(type.Name, entity); 26 27 changedCount = context.SaveChanges(); 28 if (changedCount > 0) 29 context.AcceptAllChanges(); 30 } 31 } 32 catch (Exception ex) 33 { ... } 34 return changedCount; 35 } 36 } 37 } 在一对多,多对一关系时,也可以使用以下方法进行导航属性的同步更新。首先通过反射获取主实 体的主键 Id,然后建立 EntityKey 对象,再通过 ObjectContext.GetObjectByKey(entityKey)方法在当前 上下文当中获取此实体,最后通过 ObjectContext.ApplyCurrentValues 方法,把新加入的实 体的属性复制当前上下文。 下一步就是对导航属性进行更新,首先通过反射获取外键属性,然后对一对多,多对一的关系进行 分别处理。在一对多关系时,把导航属性转换成 EntityCollection对象集合,然后通过 ObjectContext.ApplyCurrentValues 方法对集合中的每个对象进行逐个更新。 在多对一关系时,直接把导航属性转换成 T2 类型的对象进行更新。 1 public int Update(T1 entity) 2 where T1 : EntityObject 3 where T2 : EntityObject 4 { 5 lock (o) 6 { 7 int changedCount = 0; 8 Type typeT1 = typeof(T1); 9 Type typeT2 = typeof(T2); 10 try 11 { 12 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 13 { 14 PropertyInfo property = typeT1.GetProperty("Id"); 15 object id = property.GetValue(entity, null); 16 17 //根据软件 Id建立 EntityKey对象 18 EntityKey entityKey = new EntityKey("BasicArchitectureEntities." 19 + typeT1.Name, "Id", id); 20 //根据 EntityKey查找对应对象 21 T1 objT1 = context.GetObjectByKey(entityKey) as T1; 22 //在上下文中更新当前对象 23 if (objT1 != null) 24 context.ApplyCurrentValues(typeT1.Name, entity); 25 26 //获取外键属性 27 PropertyInfo propertyInfo = typeT1.GetProperty(typeT2.Name); 28 29 //在一对多关键时更新导航属性 30 var T2List = propertyInfo.GetValue(entity, null) 31 as EntityCollection; 32 if (T2List != null) 33 { 34 foreach (var obj in T2List.ToList()) 35 { 36 var oldEntity = context.GetObjectByKey(obj.EntityKey); 37 if (oldEntity != null) 38 context.ApplyCurrentValues(typeT2.Name, obj); 39 } 40 } 41 42 //在多对一,一对一关系时更新导航属性 43 var objT2 = propertyInfo.GetValue(entity, null) as T2; 44 if (objT2!= null) 45 { 46 var oldEntity = context.GetObjectByKey(objT2.EntityKey); 47 if (oldEntity != null) 48 context.ApplyCurrentValues(typeT2.Name, objT2); 49 } 50 51 changedCount = context.SaveChanges(); 52 if (changedCount > 0) 53 context.AcceptAllChanges(); 54 } 55 catch (Exception ex) 56 { ...... } 57 return changedCount; 58 } 59 } 通过此方法,无论你要通过 Company 同步更新 Position,还是反过来通过 Position 同步更新 Company,系统也能正常运行。 4. Read Read 是 CRUD 中最常见的,下面就为大家介绍最通用的几种方法 4.1 通过 Id 获取单个实体 1 public T GetObject(int id) where T : EntityObject 2 { 3 try 4 { 5 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 6 { 7 EntityKey entityKey = new EntityKey("BasicArchitectureEntities." 8 + typeof(T).Name, "Id", id); 9 var objResult = context.GetObjectByKey(entityKey); 10 return objResult as T; 11 } 12 } 13 catch (Exception ex) 14 { 15 return null; 16 } 17 } 4.2 通过输入的 Func委托获取对象 1 public T GetObject(Func predicate) where T : EntityObject 2 { 3 try 4 { 5 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 6 { 7 var objectSet = context.CreateObjectSet().Where(predicate); 8 if (objectSet.Count() > 0) 9 return objectSet.First(); 10 else 11 return null; 12 } 13 } 14 catch (Exception ex) 15 { 16 return null; 17 } 18 } 4.3 通过输入的 Func委托获取对象,并同时加载单个导航属性 1 public T GetObject(Func predicate,string includePath) 2 where T : EntityObject 3 { 4 try 5 { 6 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 7 { 8 var objectQuery = context.CreateObjectSet() 9 .Include(includePath) 10 .Where(predicate); 11 12 if (objectQuery.Count() > 0) 13 return objectQuery.First(); 14 else 15 return null; 16 } 17 } 18 catch (Exception ex) 19 { 20 return null; 21 } 22 } 4.4 通过输入的 Func委托获取对象,并同时加载多个导航属性 1 public T GetObject(Func predicate, string[] includePath) 2 where T : EntityObject 3 { 4 try 5 { 6 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 7 { 8 var list = context.CreateObjectSet().Where("1==1"); 9 10 foreach (var path in includePath) 11 list=list.Include(path); 12 13 var returnValue = list.Where(predicate).ToList(); 14 15 if (returnValue.Count() > 0) 16 return returnValue.First(); 17 else 18 return null; 19 } 20 } 21 catch (Exception ex) 22 { 23 return null; 24 } 25 } 4.5 通过输入的 Func委托获取对象集合 1 public IList GetList(Func func) where T:EntityObject 2 { 3 try 4 { 5 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 6 { 7 ObjectSet objectSet = context.CreateObjectSet(); 8 IList list = objectSet.Where(func).ToList(); 9 return list; 10 } 11 } 12 catch (Exception ex) 13 { 14 return null; 15 } 16 } 4.6 通过输入的 Func委托获取对象集合,并同时加入单个导航属性 1 public IList GetList(Func func,string includePath) 2 where T : EntityObject 3 { 4 try 5 { 6 using (BasicArchitectureEntities context = new BasicArchitectureEntities()) 7 { 8 ObjectSet objectSet = context.CreateObjectSet(); 9 IList list = objectSet.Include(includePath).Where(func).ToList(); 10 return list; 11 } 12 } 13 catch (Exception ex) 14 { 15 return null; 16 } 17 } 4.7 通过输入的 Func委托获取对象集合,并同时加入多个导航属性 1 public IList GetList(Func func, string[
本文档为【ADO.NET EF 资料】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_388858
暂无简介~
格式:pdf
大小:294KB
软件:PDF阅读器
页数:0
分类:互联网
上传时间:2012-11-30
浏览量:15