知识大全 Entity Framework数据转换层通用类
Posted 实体
篇首语:于今腐草无萤火,终古垂杨有暮鸦。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Entity Framework数据转换层通用类相关的知识,希望对你有一定的参考价值。
Entity Framework数据转换层通用类 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
在实现基础的三层开发的时候 大家时常会在数据层对每个实体进行CRUD的操作 其中存在相当多的重复代码 为了减少重复代码的出现 通常都会定义一个共用类 实现相似的操作 下面为大家介绍一下Entity Framework时常用到的通用类 首先在数据库建立起几个关联表 Person Company Position 三个实体之间通过导航属性进行相互引用
下面为大家分别介绍以泛型实现的 Create Read Update Delete 操作 Create 在ObjectContext类之中 早已经为大家预定了一个Create 的操作 AddObject: void ObjectContext AddObject(entitySetName string object entity) void ObjectSet<T> AddObject(T entity) public int Add<T>(T entity) where T : EntityObject int changedCount = ; using (TransactionScope scope = new TransactionScope(TransactionScopeOption Required)) try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) context AddObject(typeof(T) Name entity) changedCount = context SaveChanges() if (changedCount > ) context AcceptAllChanges() scope Complete() catch (Exception ex) …… return changedCount; 从下面的测试可以看到 ObjectContext AddObject(entitySetName string object entity)已相当成熟 它不但可以加入单个实体 也可通过导航属性 一次性加入多个关联实体 static void Main(string[] args) BaseCommand mand = new BaseCommand() //建立关联实体 Company pany = new Company() CompanyName = Sun Address= Beijing Telephone= ; Position position = new Position() PositionName = Project Manager Salary = Company = pany ; //通过Add<T>同时加入实体对象pany与position int n=mand Add<Position>(position) Console ReadKey()
若要使用批量插入 只要在AddObject方法前多加一个重复语言即可 在此就不再多作解释了 public int AddList<T>(List<T> entityList) where T : EntityObject int changedCount = ; using (TransactionScope scope = new TransactionScope(TransactionScopeOption Required)) try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) foreach (T entity in entityList) context AddObject(typeof(T) Name entity) changedCount = context SaveChanges() if (changedCount > ) context AcceptAllChanges() scope Complete() catch (Exception ex) …… return changedCount; Delete 同样地 ObjectContext 类当中也存在方法 ObjectContext DeleteObject(object entity)用于删除实体 首先通过输入的参数 id 建立起EntityKey对象 然后在ObjectContext查找此实体 若实体存在则使用ObjectContext DeleteObject(object entity)方法把此实体删除 public int Delete<T>(int id) where T : EntityObject int changedCount = ; using (TransactionScope scope = new TransactionScope(TransactionScopeOption Required)) try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) //建立EntityKey对象 EntityKey entityKey = new EntityKey( BasicArchitectureEntities + typeof(T) Name Id id) //通过EntityKey找到实体 var objResult = context GetObjectByKey(entityKey) //若实体存在则删除实体 if (objResult != null) context DeleteObject(objResult) changedCount = context SaveChanges() if (changedCount > ) context AcceptAllChanges() scope Complete() catch (Exception ex) …… return changedCount; ObjectContext DeleteObject(object entity)与ObjectContext AddObject(entitySetName string object entity)相同 可以通过导航属性 一次性删除多个关联实体 但如果数据库中存在下面的数据 Company表 Position表 此时使用此 int Delete<Company>( ) 方法删除Company对象 系统将会报错 这是由于导航属性在默认情况下具有延时加载的特性 在系统使用ObjectContext GetObjectByKey(entityKey)方法加载实体时 它的导航属性不会马上加载到上下文当中 而是在调用该导航属性时 对象才会被加载 因而系统通过ObjectContext GetObjectByKey( )获取Company对象时 对应的Position对象并未被加载到上下文当中 所以当删除Company对象时 Position对象不能被同步删除 因而造成逻辑上的错误 为解决这一问题 可以利用RelatedEnd Load()方法提前加载导航属性 RelatedEnd是EntityCollection<TEntity> EntityReference的父类 它们是特定实体类型的对象集合 该实体类型表示一对多 多对一 多对多的关系 而RelatedEnd Load()方法 可以将一个或多个相关对象提前加载到相关实体当中 首先通过ObjectContext GetObjectByKey(entityKey)方法找到Company对象 然后利用反射属性PropertyInfo类获取导航属性Position 最后使用RelatedEnd Load()方法 把导航属性加载到当前上下文中 此时使用Delete<Company Position>( )方法删除Company对象时 系统将能正常运行 并把对应的Position对象一并删除 public int Delete<PKEntity FKEntity>(int id) where PKEntity : EntityObject where FKEntity : EntityObject int changedCount = ; using (TransactionScope scope = new TransactionScope(TransactionScopeOption Required)) try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) //根据软件Id建立EntityKey对象 EntityKey entityKey = new EntityKey( BasicArchitectureEntities + typeof(PKEntity) Name Id id) //根据EntityKey查找对应对象 PKEntity objResult = context GetObjectByKey(entityKey) as PKEntity; //根据FKEntity加载导航属性 PropertyInfo propertyInfo = typeof(PKEntity) GetProperty(typeof(FKEntity) Name) EntityCollection<FKEntity> FKEntityList = propertyInfo GetValue(objResult null) as EntityCollection<FKEntity>; if (FKEntityList != null) FKEntityList Load() if (objResult != null) context DeleteObject(objResult) changedCount = context SaveChanges() if (changedCount > ) context AcceptAllChanges() scope Complete() catch (Exception ex) …… return changedCount; 通过下面的方法也可根据输入的委托predicate 批量删除有关的数据 public int Delete<T>(Func<T bool> predicate) where T: EntityObject int changedCount = ; using (TransactionScope scope = new TransactionScope(TransactionScopeOption Required)) try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) //根据输入的委托查找数据 var list = context CreateObjectSet<T>() Where(predicate) //若存在数据 删除有关数据 if (list Count() > ) foreach (var obj in list) context DeleteObject(obj) changedCount = context SaveChanges() if (changedCount > ) context AcceptAllChanges() scope Complete() catch (Exception ex) …… return changedCount; 与前面的例子相同 当使用 Delete<Company>(x=>x Id== ) 方法删除 Company 对象时 由于导航属性 Position 处于延迟加载的状态 以致系统无法实现同步删除 从而令数据出现逻辑性的错误 此时使用类似的方法 利用 RelatedEnd Load() 把导航属性提前加入到上下文中 再删除Company对象时 系统就可以把对应 Position 对象一并删除 public int Delete<PKEntity FKEntity>(Func<PKEntity bool> predicate) where PKEntity : EntityObject where FKEntity : EntityObject int changedCount = ; using (TransactionScope scope = new TransactionScope(TransactionScopeOption Required)) try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) //根据输入的委托查找数据 var list = context CreateObjectSet<PKEntity>() Where(predicate) //若数目大于 删除有关数据 if (list Count() > ) foreach (var obj in list) //在删除前加载其导航属性 PropertyInfo propertyInfo = typeof(PKEntity) GetProperty(typeof(FKEntity) Name) EntityCollection<FKEntity> FKEntityList = propertyInfo GetValue(obj null) as EntityCollection<FKEntity>; if (FKEntityList Count > ) FKEntityList Load() context DeleteObject(obj) changedCount = context SaveChanges() if (changedCount > ) context AcceptAllChanges() scope Complete() catch (Exception ex) …… return changedCount; 此时使用Delete<Company Position>(x=>x Id== ) 这样就可以把Company对象和相关的Position对象同时删除 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> 方法 把新加入的实体的属性复制当前上下文 public class BaseCommand private object o = new object() public int Update<T>(T entity) where T : EntityObject lock (o) int changedCount = ; Type type = typeof(T) using (TransactionScope scope = new TransactionScope(TransactionScopeOption Required)) try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) //获取实体的Id属性 PropertyInfo property = type GetProperty( Id ) object id = property GetValue(entity null) //根据Id获取上下文中的对应实体 EntityKey entityKey = new EntityKey( BasicArchitectureEntities + type Name Id id) var objResult = context GetObjectByKey(entityKey) //更新实体属性 if (objResult != null) context ApplyCurrentValues<T>(type Name entity) changedCount = context SaveChanges() if (changedCount > ) context AcceptAllChanges() scope Complete() catch (Exception ex) … return changedCount; 在一对多 多对一关系时 也可以使用以下方法进行导航属性的同步更新 首先通过反射获取主实体的主键Id 然后建立EntityKey对象 再通过ObjectContext GetObjectByKey(entityKey)方法在当前上下文当中获取此实体 最后通过 ObjectContext ApplyCurrentValues<TEntity> 方法 把新加入的实体的属性复制当前上下文 下一步就是对导航属性进行更新 首先通过反射获取外键属性 然后对一对多 多对一的关系进行分别处理 在一对多关系时 把导航属性转换成EntityCollection<T >对象集合 然后通过 ObjectContext ApplyCurrentValues<TEntity> 方法对集合中的每个对象进行逐个更新 在多对一关系时 直接把导航属性转换成T 类型的对象进行更新 public int Update<T T >(T entity) where T : EntityObject where T : EntityObject lock (o) int changedCount = ; Type typeT = typeof(T ) Type typeT = typeof(T ) using (TransactionScope scope = new TransactionScope(TransactionScopeOption Required)) try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) PropertyInfo property = typeT GetProperty( Id ) object id = property GetValue(entity null) //根据软件Id建立EntityKey对象 EntityKey entityKey = new EntityKey( BasicArchitectureEntities + typeT Name Id id) //根据EntityKey查找对应对象 T objT = context GetObjectByKey(entityKey) as T ; //在上下文中更新当前对象 if (objT != null) context ApplyCurrentValues<T >(typeT Name entity) //获取外键属性 PropertyInfo propertyInfo = typeT GetProperty(typeT Name) //在一对多关键时更新导航属性 var T List = propertyInfo GetValue(entity null) as EntityCollection<T >; if (T List != null) foreach (var obj in T List ToList()) var oldEntity = context GetObjectByKey(obj EntityKey) if (oldEntity != null) context ApplyCurrentValues<T >(typeT Name obj) //在多对一 一对一关系时更新导航属性 var objT = propertyInfo GetValue(entity null) as T ; if (objT != null) var oldEntity = context GetObjectByKey(objT EntityKey) if (oldEntity != null) context ApplyCurrentValues<T >(typeT Name objT ) changedCount = context SaveChanges() if (changedCount > ) context AcceptAllChanges() scope Complete() catch (Exception ex) …… return changedCount; 通过此方法 无论你要通过Company同步更新Position 还是反过来通过Position同步更新Company 系统也能正常运行 Read Read 是CRUD中最常见的 下面就为大家介绍最通用的几种方法 通过Id获取单个实体 public T GetObject<T>(int id) where T : EntityObject try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) EntityKey entityKey = new EntityKey( BasicArchitectureEntities + typeof(T) Name Id id) var objResult = context GetObjectByKey(entityKey) return objResult as T; catch (Exception ex) return null; 通过输入的Func<T bool>委托获取对象 public T GetObject<T>(Func<T bool> predicate) where T : EntityObject try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) var objectSet = context CreateObjectSet<T>() Where(predicate) if (objectSet Count() > ) return objectSet First() else return null; catch (Exception ex) return null; 通过输入的Func<T bool>委托获取对象 并同时加载单个导航属性 public T GetObject<T>(Func<T bool> predicate string includePath) where T : EntityObject try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) var objectQuery = context CreateObjectSet<T>() Include(includePath) Where(predicate) if (objectQuery Count() > ) return objectQuery First() else return null; catch (Exception ex) return null; 通过输入的Func<T bool>委托获取对象 并同时加载多个导航属性 public T GetObject<T>(Func<T bool> predicate string[] includePath) where T : EntityObject try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) var list = context CreateObjectSet<T>() Where( == ) foreach (var path in includePath) list=list Include(path) var returnValue = list Where(predicate) ToList() if (returnValue Count() > ) return returnValue First() else return null; catch (Exception ex) return null; 通过输入的Func<T bool>委托获取对象集合 public IList<T> GetList<T>(Func<T bool> func) where T:EntityObject try using (BasicArchitectureEntities context = new BasicArchitectureEntities()) ObjectSet<T> objectSet = context CreateObjectSet<T>() IList<T> list = objectSet Where(func) ToList() return list; catch (Exception ex) &nb相关参考
知识大全 ADO.NET Entity Framework存取数据库中的图片
ADO.NETEntityFramework存取数据库中的图片 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来
EntityFramework细节追踪 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 为了加深对
知识大全 ADO.NET Entity Framework—并发
ADO.NETEntityFramework—并发 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
知识大全 ADO.NET Entity Framework 试水——并发
ADO.NETEntityFramework试水——并发 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下
知识大全 ADO.NET Entity Framework 试水——并发[4]
ADO.NETEntityFramework试水——并发[4] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来
知识大全 ADO.NET Entity Framework 试水——并发[3]
ADO.NETEntityFramework试水——并发[3] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来
知识大全 ADO.NET Entity Framework 试水——并发[1]
ADO.NETEntityFramework试水——并发[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来
知识大全 ADO.NET Entity Framework 试水——并发[2]
ADO.NETEntityFramework试水——并发[2] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来
知识大全 ADO.NET Entity Framework 入门示例向导
ADO.NETEntityFramework入门示例向导 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下
应用概述 通用数据转换工具在油气藏地质及开发工程国家重点实验室项目(PLN)油藏经营管理系统中作为其数据转换的功能模块之一运用于大港油田历史数据转换到新的油藏经营管理数据库中通用数据转换工具作为