主题:.net基础知识大全,免费奉送
在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行CRUD的操作,其中存在相当多的重复代码。为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大家介绍一下Entity Framework时常用到的通用类。资料出自http://www.chinabenet.com
首先在数据库建立起几个关联表:Person、Company、Position,三个实体之间通过导航属性进行相互引用。
下面为大家分别介绍以泛型实现的 Create、Read、Update、Delete 操作:
1. Create
在ObjectContext类之中,早已经为大家预定了一个Create 的操作 AddObject:
void ObjectContext.AddObject(entitySetName string,object entity)
void ObjectSet<T>.AddObject(T entity)
1 public int Add<T>(T entity) where T : EntityObject
2 {
3 int changedCount = 0;
4 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
5 {
6 try
7 {
8 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
9 {
10 context.AddObject(typeof(T).Name, entity);
11 changedCount = context.SaveChanges();
12 if (changedCount > 0)
13 context.AcceptAllChanges();
14 scope.Complete();
15 }
16 }
17 catch (Exception ex)
18 { ........ }
19 }
20 return changedCount;
21 }
从下面的测试可以看到,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" ,Address="Beijing",Telephone="010-87654321"};
6 Position position = new Position() { PositionName = "Project Manager", Salary = 15000.00, Company = company };
7 //通过Add<T>同时加入实体对象company与position
8 int n=command.Add<Position>(position);
9
10 Console.ReadKey();
11 }
若要使用批量插入,只要在AddObject方法前多加一个重复语言即可,在此就不再多作解释了。
1 public int AddList<T>(List<T> entityList) where T : EntityObject
2 {
3 int changedCount = 0;
4 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
5 {
6 try
7 {
8 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
9 {
10 foreach (T entity in entityList)
11 context.AddObject(typeof(T).Name, entity);
12 changedCount = context.SaveChanges();
13 if (changedCount > 0)
14 context.AcceptAllChanges();
15 scope.Complete();
16 }
17 }
18 catch (Exception ex)
19 { ....... }
20 }
21 return changedCount;
22 }
2. Delete
同样地,ObjectContext 类当中也存在方法 ObjectContext.DeleteObject(object entity)用于删除实体。
首先通过输入的参数 id 建立起EntityKey对象,然后在ObjectContext查找此实体,若实体存在则使用ObjectContext.DeleteObject(object entity)方法把此实体删除 。
1 public int Delete<T>(int id) where T : EntityObject
2 {
3 int changedCount = 0;
4 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
5 {
6 try
7 {
8 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
9 {
10 //建立EntityKey对象
11 EntityKey entityKey = new EntityKey("BasicArchitectureEntities." + typeof(T).Name, "Id", id);
12 //通过EntityKey找到实体
13 var objResult = context.GetObjectByKey(entityKey);
14 //若实体存在则删除实体
15 if (objResult != null)
16 context.DeleteObject(objResult);
17 changedCount = context.SaveChanges();
18 if (changedCount > 0)
19 context.AcceptAllChanges();
20
21 scope.Complete();
22 }
23 }
24 catch (Exception ex)
25 { ...... }
26 }
27 return changedCount;
28 }
ObjectContext.DeleteObject(object entity)与ObjectContext.AddObject(entitySetName string,object entity)相同,可以通过导航属性,一次性删除多个关联实体。但如果数据库中存在下面的数据
Company表:
Position表:
此时使用此 int Delete<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对象一并删除。
1 public int Delete<PKEntity, FKEntity>(int id)
2 where PKEntity : EntityObject
3 where FKEntity : EntityObject
4 {
5 int changedCount = 0;
6 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
7 {
8 try
9 {
10 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
11 {
12 //根据软件Id建立EntityKey对象
13 EntityKey entityKey = new EntityKey("BasicArchitectureEntities." + typeof(PKEntity).Name, "Id", id);
14 //根据EntityKey查找对应对象
15 PKEntity objResult = context.GetObjectByKey(entityKey) as PKEntity;
16 //根据FKEntity加载导航属性
17 PropertyInfo propertyInfo = typeof(PKEntity).GetProperty(typeof(FKEntity).Name);
18 EntityCollection<FKEntity> FKEntityList = propertyInfo.GetValue(objResult, null)
19 as EntityCollection<FKEntity>;
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 scope.Complete();
32 }
33 }
34 catch (Exception ex)
35 { ........ }
36 }
37 return changedCount;
38 }
通过下面的方法也可根据输入的委托predicate,批量删除有关的数据。
1 public int Delete<T>(Func<T,bool> predicate) where T: EntityObject
2 {
3 int changedCount = 0;
4 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
5 {
6 try
7 {
8 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
9 {
10 //根据输入的委托查找数据
11 var list = context.CreateObjectSet<T>().Where(predicate);
12 //若存在数据,删除有关数据
13 if (list.Count() > 0)
14 foreach (var obj in list)
15 context.DeleteObject(obj);
16
17 changedCount = context.SaveChanges();
18 if (changedCount > 0)
19 context.AcceptAllChanges();
20
21 scope.Complete();
22 }
23 }
24 catch (Exception ex)
25 { ...... }
26 }
27 return changedCount;
28 }
与前面的例子相同,当使用 Delete<Company>(x=>x.Id==2) 方法删除 Company 对象时,由于导航属性 Position 处于延迟加载的状态,以致系统无法实现同步删除,从而令数据出现逻辑性的错误。
此时使用类似的方法,利用 RelatedEnd.Load() 把导航属性提前加入到上下文中,再删除Company对象时,系统就可以把对应 Position 对象一并删除。
[url=http://www.chinabenet.com]北大青鸟网站[/url]
首先在数据库建立起几个关联表:Person、Company、Position,三个实体之间通过导航属性进行相互引用。
下面为大家分别介绍以泛型实现的 Create、Read、Update、Delete 操作:
1. Create
在ObjectContext类之中,早已经为大家预定了一个Create 的操作 AddObject:
void ObjectContext.AddObject(entitySetName string,object entity)
void ObjectSet<T>.AddObject(T entity)
1 public int Add<T>(T entity) where T : EntityObject
2 {
3 int changedCount = 0;
4 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
5 {
6 try
7 {
8 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
9 {
10 context.AddObject(typeof(T).Name, entity);
11 changedCount = context.SaveChanges();
12 if (changedCount > 0)
13 context.AcceptAllChanges();
14 scope.Complete();
15 }
16 }
17 catch (Exception ex)
18 { ........ }
19 }
20 return changedCount;
21 }
从下面的测试可以看到,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" ,Address="Beijing",Telephone="010-87654321"};
6 Position position = new Position() { PositionName = "Project Manager", Salary = 15000.00, Company = company };
7 //通过Add<T>同时加入实体对象company与position
8 int n=command.Add<Position>(position);
9
10 Console.ReadKey();
11 }
若要使用批量插入,只要在AddObject方法前多加一个重复语言即可,在此就不再多作解释了。
1 public int AddList<T>(List<T> entityList) where T : EntityObject
2 {
3 int changedCount = 0;
4 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
5 {
6 try
7 {
8 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
9 {
10 foreach (T entity in entityList)
11 context.AddObject(typeof(T).Name, entity);
12 changedCount = context.SaveChanges();
13 if (changedCount > 0)
14 context.AcceptAllChanges();
15 scope.Complete();
16 }
17 }
18 catch (Exception ex)
19 { ....... }
20 }
21 return changedCount;
22 }
2. Delete
同样地,ObjectContext 类当中也存在方法 ObjectContext.DeleteObject(object entity)用于删除实体。
首先通过输入的参数 id 建立起EntityKey对象,然后在ObjectContext查找此实体,若实体存在则使用ObjectContext.DeleteObject(object entity)方法把此实体删除 。
1 public int Delete<T>(int id) where T : EntityObject
2 {
3 int changedCount = 0;
4 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
5 {
6 try
7 {
8 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
9 {
10 //建立EntityKey对象
11 EntityKey entityKey = new EntityKey("BasicArchitectureEntities." + typeof(T).Name, "Id", id);
12 //通过EntityKey找到实体
13 var objResult = context.GetObjectByKey(entityKey);
14 //若实体存在则删除实体
15 if (objResult != null)
16 context.DeleteObject(objResult);
17 changedCount = context.SaveChanges();
18 if (changedCount > 0)
19 context.AcceptAllChanges();
20
21 scope.Complete();
22 }
23 }
24 catch (Exception ex)
25 { ...... }
26 }
27 return changedCount;
28 }
ObjectContext.DeleteObject(object entity)与ObjectContext.AddObject(entitySetName string,object entity)相同,可以通过导航属性,一次性删除多个关联实体。但如果数据库中存在下面的数据
Company表:
Position表:
此时使用此 int Delete<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对象一并删除。
1 public int Delete<PKEntity, FKEntity>(int id)
2 where PKEntity : EntityObject
3 where FKEntity : EntityObject
4 {
5 int changedCount = 0;
6 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
7 {
8 try
9 {
10 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
11 {
12 //根据软件Id建立EntityKey对象
13 EntityKey entityKey = new EntityKey("BasicArchitectureEntities." + typeof(PKEntity).Name, "Id", id);
14 //根据EntityKey查找对应对象
15 PKEntity objResult = context.GetObjectByKey(entityKey) as PKEntity;
16 //根据FKEntity加载导航属性
17 PropertyInfo propertyInfo = typeof(PKEntity).GetProperty(typeof(FKEntity).Name);
18 EntityCollection<FKEntity> FKEntityList = propertyInfo.GetValue(objResult, null)
19 as EntityCollection<FKEntity>;
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 scope.Complete();
32 }
33 }
34 catch (Exception ex)
35 { ........ }
36 }
37 return changedCount;
38 }
通过下面的方法也可根据输入的委托predicate,批量删除有关的数据。
1 public int Delete<T>(Func<T,bool> predicate) where T: EntityObject
2 {
3 int changedCount = 0;
4 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
5 {
6 try
7 {
8 using (BasicArchitectureEntities context = new BasicArchitectureEntities())
9 {
10 //根据输入的委托查找数据
11 var list = context.CreateObjectSet<T>().Where(predicate);
12 //若存在数据,删除有关数据
13 if (list.Count() > 0)
14 foreach (var obj in list)
15 context.DeleteObject(obj);
16
17 changedCount = context.SaveChanges();
18 if (changedCount > 0)
19 context.AcceptAllChanges();
20
21 scope.Complete();
22 }
23 }
24 catch (Exception ex)
25 { ...... }
26 }
27 return changedCount;
28 }
与前面的例子相同,当使用 Delete<Company>(x=>x.Id==2) 方法删除 Company 对象时,由于导航属性 Position 处于延迟加载的状态,以致系统无法实现同步删除,从而令数据出现逻辑性的错误。
此时使用类似的方法,利用 RelatedEnd.Load() 把导航属性提前加入到上下文中,再删除Company对象时,系统就可以把对应 Position 对象一并删除。
[url=http://www.chinabenet.com]北大青鸟网站[/url]