博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF架构~一个规范,两个实现
阅读量:7012 次
发布时间:2019-06-28

本文共 20662 字,大约阅读时间需要 68 分钟。

在EF环境里,我们的数据上下文对象通常是有两个版本,一个是DbContext对象,另一个是ObjectContext,个人觉得前者是轻量级的,对于code first模式中使用比较多,而后者是原生态的,最初的EDM(entity Data Model)就是以这个为基类的,它的实现与linq to sql很类似,也是分部方法,lambda表达式等元素的产物。

看看我的一个规范,两个实现吧!

一个规范:

1 namespace Commons.Data  2 {  3     ///   4     /// data repository interface  5     ///   6     /// 
7 public interface IRepository 8 { 9 /// 10 /// 添加 11 /// 12 /// 13 void Insert
(TEntity entity, bool isSubmit) where TEntity : class; 14 ///
15 /// 添加并提交 16 /// 17 ///
18 ///
19 void Insert
(TEntity entity) where TEntity : class; 20 ///
21 /// 批量添加并提交 22 /// 23 ///
24 ///
25 void Insert
(List
list) where TEntity : class; 26 ///
27 /// 更新 28 /// 29 ///
30 void Update
(TEntity entity, bool isSubmit) where TEntity : class; 31 ///
32 /// 更新并提交 33 /// 34 ///
35 ///
36 void Update
(TEntity entity) where TEntity : class; 37 ///
38 /// 更新列表 39 /// 40 ///
41 ///
42 void Update
(List
list) where TEntity : class; 43 ///
44 /// 更新指定字段 45 /// 46 ///
47 ///
48 void Update
(Expression
> entity, bool isSubmit) where TEntity : class; 49 ///
50 /// 更新指定字段并提交 51 /// 52 ///
53 ///
54 void Update
(Expression
> entity) where TEntity : class; 55 ///
56 /// 删除 57 /// 58 ///
59 void Delete
(TEntity entity, bool isSubmit) where TEntity : class; 60 ///
61 /// 删除并提交 62 /// 63 ///
64 ///
65 void Delete
(TEntity entity) where TEntity : class; 66 ///
67 /// 根据主键取一个 68 /// 69 ///
70 ///
71 TEntity GetEntity
(params object[] id) where TEntity : class; 72 ///
73 /// 根据条件取一个 74 /// 75 ///
76 ///
77 TEntity GetEntity
(Expression
> predicate) where TEntity : class; 78 ///
79 /// 实体集对象的可查询结果集 80 /// 81 IQueryable
GetEntities
() where TEntity : class; 82 ///
83 /// 统计数量 84 /// 85 ///
86 ///
87 int Count
(Expression
> predicate) where TEntity : class; 88 ///
89 /// 返回结果集 90 /// 91 ///
92 ///
93 IEnumerable
GetEntities
(Expression
> predicate) where TEntity : class; 94 ///
95 /// 带有排序的结果集 96 /// 97 ///
98 ///
99 ///
100 IEnumerable
GetEntities
(Expression
> predicate, Action
> order) where TEntity : class;101 ///
102 /// 带分页和排序的结果集103 /// 104 ///
105 ///
106 ///
107 ///
108 ///
109 IEnumerable
GetEntities
(Expression
> predicate, Action
> order, int skip, int count) where TEntity : class;110 111 }112 }

两个实现:

一 DbContext作为基类的实现:

1 namespace Commons.Data  2 {  3     ///   4     /// EF数据结构实现  5     ///   6     /// 
7 public abstract class RepositoryBase : IRepository 8 { 9 #region Properties 10 /// 11 /// 日志对象 12 /// 13 public VLog.IVLog _iVlog { get; set; } 14 /// 15 /// 数据上下文,对子类公开 16 /// 17 protected readonly DbContext _db; 18 #endregion 19 20 #region Constructors 21 /// 22 /// 通过具体子类建立DbContext对象,并提供日志对象的实现 23 /// 24 /// 25 /// 26 public RepositoryBase(DbContext db, VLog.IVLog logger) 27 { 28 try 29 { 30 _db = db; 31 _iVlog = logger; 32 } 33 catch (Exception) 34 { 35 36 throw new Exception("EF底层数据出现问题,请检查..."); 37 } 38 39 } 40 41 public RepositoryBase(DbContext db) 42 : this(db, null) 43 { 44 45 } 46 47 #endregion 48 49 #region IRepository
成员 50 51 #region Create,Update,Delete --Virtual Methods 52 53 #region 简单调用 54 public virtual void Insert
(TEntity entity) where TEntity : class 55 { 56 this.Insert(entity, true); 57 } 58 59 public void Insert
(List
list) where TEntity : class 60 { 61 BulkInsertAll
(list); 62 } 63 64 public void Update
(TEntity entity) where TEntity : class 65 { 66 this.Update
(entity, true); 67 } 68 69 public void Update
(List
list) where TEntity : class 70 { 71 list.ForEach(entity => 72 { 73 this.Update
(entity, false); 74 }); 75 this.SaveChanges(); 76 } 77 78 public virtual void Update
(Expression
> entity) where TEntity : class 79 { 80 this.Update
(entity, true); 81 } 82 83 public virtual void Delete
(TEntity entity) where TEntity : class 84 { 85 this.Delete
(entity, true); 86 } 87 #endregion 88 89 #region GUID操作实现 90 public void Insert
(TEntity entity, bool isSubmit) where TEntity : class 91 { 92 //Logger.InfoLog("Create 表名:{0},内容:{1}", entity, ToJson(entity)); 93 _db.Entry
(entity); 94 _db.Set
().Add(entity); 95 if (isSubmit) 96 this.SaveChanges(); 97 } 98 99 public void Update
(TEntity entity, bool isSubmit) where TEntity : class100 {101 _db.Set
().Attach(entity);102 _db.Entry(entity).State = EntityState.Modified;103 if (isSubmit)104 this.SaveChanges();105 }106 107 public void Update
(Expression
> entity, bool isSubmit) where TEntity : class108 {109 TEntity newEntity = typeof(TEntity).GetConstructor(Type.EmptyTypes).Invoke(null) as TEntity;//建立指定类型的实例110 List
propertyNameList = new List
();111 MemberInitExpression param = entity.Body as MemberInitExpression;112 foreach (var item in param.Bindings)113 {114 string propertyName = item.Member.Name;115 object propertyValue;116 var memberAssignment = item as MemberAssignment;117 if (memberAssignment.Expression.NodeType == ExpressionType.Constant)118 {119 propertyValue = (memberAssignment.Expression as ConstantExpression).Value;120 }121 else122 {123 propertyValue = Expression.Lambda(memberAssignment.Expression, null).Compile().DynamicInvoke();124 }125 typeof(TEntity).GetProperty(propertyName).SetValue(newEntity, propertyValue, null);126 propertyNameList.Add(propertyName);127 }128 _db.Set
().Attach(newEntity);129 _db.Configuration.ValidateOnSaveEnabled = false;130 var ObjectStateEntry = ((IObjectContextAdapter)_db).ObjectContext.ObjectStateManager.GetObjectStateEntry(newEntity);131 propertyNameList.ForEach(x => ObjectStateEntry.SetModifiedProperty(x.Trim()));132 if (isSubmit)133 this.SaveChanges();134 }135 136 public void Delete
(TEntity entity, bool isSubmit) where TEntity : class137 {138 _db.Set
().Attach(entity);139 _db.Set
().Remove(entity);140 if (isSubmit)141 this.SaveChanges();142 }143 #endregion144 145 #endregion146 147 #region Get --Virtual Methods148 public virtual int Count
(Expression
> predicate) where TEntity : class149 {150 return GetEntities(predicate).Count();151 }152 153 public virtual TEntity GetEntity
(params object[] id) where TEntity : class154 {155 return _db.Set
().Find(id);156 }157 public virtual TEntity GetEntity
(Expression
> predicate) where TEntity : class158 {159 return GetEntities(predicate).SingleOrDefault();160 }161 162 public virtual IQueryable
GetEntities
() where TEntity : class163 {164 return _db.Set
();165 }166 public virtual IEnumerable
GetEntities
(Expression
> predicate) where TEntity : class167 {168 return this.GetEntities
().Where(predicate);169 }170 171 public virtual IEnumerable
GetEntities
(Expression
> predicate, Action
> order) where TEntity : class172 {173 var orderable = new Orderable
(GetEntities(predicate).AsQueryable());174 order(orderable);175 return orderable.Queryable;176 }177 178 public virtual IEnumerable
GetEntities
(Expression
> predicate, Action
> order, int skip, int count) where TEntity : class179 {180 return GetEntities(predicate, order).Skip(skip).Take(count);181 }182 #endregion183 184 #endregion185 186 #region Methods187 ///
188 /// 提交动作189 /// 当程序中出现SaveChanges开始与数据库进行通讯190 /// 191 protected virtual void SaveChanges()192 {193 try194 {195 _db.SaveChanges(); //在有196 }197 catch (Exception ex)198 {199 string Message = "error:";200 if (ex.InnerException == null)201 Message += ex.Message + ",";202 else if (ex.InnerException.InnerException == null)203 Message += ex.InnerException.Message + ",";204 else if (ex.InnerException.InnerException.InnerException == null)205 Message += ex.InnerException.InnerException.Message + ",";206 throw new Exception(Message);207 }208 }209 ///
210 /// 批量插入211 /// 212 ///
213 ///
214 void BulkInsertAll
(IEnumerable
entities) where T : class215 {216 entities = entities.ToArray();217 218 string cs = _db.Database.Connection.ConnectionString;219 var conn = new SqlConnection(cs);220 conn.Open();221 222 Type t = typeof(T);223 224 var bulkCopy = new SqlBulkCopy(conn)225 {226 DestinationTableName = string.Format("[{0}]", t.Name)227 };228 229 var properties = t.GetProperties().Where(EventTypeFilter).ToArray();230 var table = new DataTable();231 232 foreach (var property in properties)233 {234 Type propertyType = property.PropertyType;235 if (propertyType.IsGenericType &&236 propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))237 {238 propertyType = Nullable.GetUnderlyingType(propertyType);239 }240 241 table.Columns.Add(new DataColumn(property.Name, propertyType));242 }243 244 foreach (var entity in entities)245 {246 table.Rows.Add(properties.Select(247 property => GetPropertyValue(248 property.GetValue(entity, null))).ToArray());249 }250 251 bulkCopy.WriteToServer(table);252 conn.Close();253 }254 255 private bool EventTypeFilter(System.Reflection.PropertyInfo p)256 {257 var attribute = Attribute.GetCustomAttribute(p,258 typeof(AssociationAttribute)) as AssociationAttribute;259 260 if (attribute == null) return true;261 if (attribute.IsForeignKey == false) return true;262 263 return false;264 }265 266 private object GetPropertyValue(object o)267 {268 if (o == null)269 return DBNull.Value;270 return o;271 }272 #endregion273 274 }275 276 }

二 ObjectContext作为基类的实现:

1 namespace Commons.Data  2 {  3     ///   4     /// EF数据结构实现  5     ///   6     /// 
7 public abstract class ObjectContextRepositoryBase : IRepository 8 { 9 #region PropertiesObjectContext 10 /// 11 /// 日志对象 12 /// 13 public VLog.IVLog _iVlog { get; set; } 14 /// 15 /// 数据上下文,对子类公开 16 /// 17 protected readonly ObjectContext _db; 18 #endregion 19 20 #region Constructors 21 /// 22 /// 通过具体子类建立DbContext对象,并提供日志对象的实现 23 /// 24 /// 25 /// 26 public ObjectContextRepositoryBase(ObjectContext db, VLog.IVLog logger) 27 { 28 try 29 { 30 _db = db; 31 _iVlog = logger; 32 } 33 catch (Exception) 34 { 35 36 throw new Exception("EF底层数据出现问题,请检查..."); 37 } 38 39 } 40 41 public ObjectContextRepositoryBase(ObjectContext db) 42 : this(db, null) 43 { 44 45 } 46 47 #endregion 48 49 #region IRepository
成员 50 51 #region Create,Update,Delete --Virtual Methods 52 53 #region 简单调用 54 public virtual void Insert
(TEntity entity) where TEntity : class 55 { 56 this.Insert(entity, true); 57 } 58 59 public void Insert
(List
list) where TEntity : class 60 { 61 // BulkInsertAll
(list); 62 list.ForEach(entity => 63 { 64 Insert(entity, false); 65 }); 66 this.SaveChanges(); 67 } 68 69 public void Update
(TEntity entity) where TEntity : class 70 { 71 // this.Update
(entity, true); 72 UpdateEntity
(entity); 73 } 74 75 public void Update
(List
list) where TEntity : class 76 { 77 list.ForEach(entity => 78 { 79 this.Update
(entity, false); 80 }); 81 this.SaveChanges(); 82 } 83 84 public virtual void Update
(Expression
> entity) where TEntity : class 85 { 86 this.Update
(entity, true); 87 } 88 89 public virtual void Delete
(TEntity entity) where TEntity : class 90 { 91 this.Delete
(entity, true); 92 } 93 #endregion 94 95 #region GUID操作实现 96 public void Insert
(TEntity entity, bool isSubmit) where TEntity : class 97 { 98 //Logger.InfoLog("Create 表名:{0},内容:{1}", entity, ToJson(entity)); 99 _db.CreateObjectSet
().AddObject(entity);100 if (isSubmit)101 this.SaveChanges();102 }103 104 public void Update
(TEntity entity, bool isSubmit) where TEntity : class105 {106 _db.Attach(entity as EntityObject);107 _db.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);108 if (isSubmit)109 this.SaveChanges();110 }111 112 public void Update
(Expression
> entity, bool isSubmit) where TEntity : class113 {114 TEntity newEntity = typeof(TEntity).GetConstructor(Type.EmptyTypes).Invoke(null) as TEntity;//建立指定类型的实例115 List
propertyNameList = new List
();116 MemberInitExpression param = entity.Body as MemberInitExpression;117 foreach (var item in param.Bindings)118 {119 string propertyName = item.Member.Name;120 object propertyValue;121 var memberAssignment = item as MemberAssignment;122 if (memberAssignment.Expression.NodeType == ExpressionType.Constant)123 {124 propertyValue = (memberAssignment.Expression as ConstantExpression).Value;125 }126 else127 {128 propertyValue = Expression.Lambda(memberAssignment.Expression, null).Compile().DynamicInvoke();129 }130 typeof(TEntity).GetProperty(propertyName).SetValue(newEntity, propertyValue, null);131 propertyNameList.Add(propertyName);132 }133 _db.Attach(newEntity as EntityObject);134 // _db.Configuration.ValidateOnSaveEnabled = false;135 var ObjectStateEntry = ((IObjectContextAdapter)_db).ObjectContext.ObjectStateManager.GetObjectStateEntry(newEntity);136 propertyNameList.ForEach(x => ObjectStateEntry.SetModifiedProperty(x.Trim()));137 if (isSubmit)138 this.SaveChanges();139 }140 141 public void Delete
(TEntity entity, bool isSubmit) where TEntity : class142 {143 _db.Attach(entity as EntityObject);144 _db.ObjectStateManager.ChangeObjectState(entity, EntityState.Deleted);145 if (isSubmit)146 this.SaveChanges();147 }148 #endregion149 150 #endregion151 152 #region Get --Virtual Methods153 public virtual int Count
(Expression
> predicate) where TEntity : class154 {155 return GetEntities(predicate).Count();156 }157 158 public virtual TEntity GetEntity
(params object[] id) where TEntity : class159 {160 //new NotImplementedException("this method don't implement by zzl !");161 return null;162 }163 public virtual TEntity GetEntity
(Expression
> predicate) where TEntity : class164 {165 return GetEntities(predicate).SingleOrDefault();166 }167 168 public virtual IQueryable
GetEntities
() where TEntity : class169 {170 return _db.CreateObjectSet
();171 }172 public virtual IEnumerable
GetEntities
(Expression
> predicate) where TEntity : class173 {174 return this.GetEntities
().Where(predicate);175 }176 177 public virtual IEnumerable
GetEntities
(Expression
> predicate, Action
> order) where TEntity : class178 {179 var orderable = new Orderable
(GetEntities(predicate).AsQueryable());180 order(orderable);181 return orderable.Queryable;182 }183 184 public virtual IEnumerable
GetEntities
(Expression
> predicate, Action
> order, int skip, int count) where TEntity : class185 {186 return GetEntities(predicate, order).Skip(skip).Take(count);187 }188 #endregion189 190 #endregion191 192 #region Methods193 ///
194 /// 提交动作195 /// 当程序中出现SaveChanges开始与数据库进行通讯196 /// 197 protected virtual void SaveChanges()198 {199 try200 {201 _db.SaveChanges(); //在有202 }203 catch (Exception ex)204 {205 string Message = "error:";206 if (ex.InnerException == null)207 Message += ex.Message + ",";208 else if (ex.InnerException.InnerException == null)209 Message += ex.InnerException.Message + ",";210 else if (ex.InnerException.InnerException.InnerException == null)211 Message += ex.InnerException.InnerException.Message + ",";212 throw new Exception(Message);213 }214 }215 ///
216 /// 批量插入217 /// 218 ///
219 ///
220 void BulkInsertAll
(IEnumerable
entities) where T : class221 {222 entities = entities.ToArray();223 224 string cs = _db.Connection.ConnectionString;225 var conn = new SqlConnection(cs);226 conn.Open();227 228 Type t = typeof(T);229 230 var bulkCopy = new SqlBulkCopy(conn)231 {232 DestinationTableName = string.Format("[{0}]", t.Name)233 };234 235 var properties = t.GetProperties().Where(EventTypeFilter).ToArray();236 var table = new DataTable();237 238 foreach (var property in properties)239 {240 Type propertyType = property.PropertyType;241 if (propertyType.IsGenericType &&242 propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))243 {244 propertyType = Nullable.GetUnderlyingType(propertyType);245 }246 247 table.Columns.Add(new DataColumn(property.Name, propertyType));248 }249 250 foreach (var entity in entities)251 {252 table.Rows.Add(properties.Select(253 property => GetPropertyValue(254 property.GetValue(entity, null))).ToArray());255 }256 257 bulkCopy.WriteToServer(table);258 conn.Close();259 }260 261 private bool EventTypeFilter(System.Reflection.PropertyInfo p)262 {263 var attribute = Attribute.GetCustomAttribute(p,264 typeof(AssociationAttribute)) as AssociationAttribute;265 266 if (attribute == null) return true;267 if (attribute.IsForeignKey == false) return true;268 269 return false;270 }271 272 private object GetPropertyValue(object o)273 {274 if (o == null)275 return DBNull.Value;276 return o;277 }278 279 private void UpdateEntity
(TEntity entity) where TEntity : class280 {281 Type entityType = entity.GetType();282 var table = entityType.GetProperties().Where(i => i.PropertyType != typeof(EntityKey) && i.PropertyType != typeof(EntityState)).ToArray();283 var primaryKeyColumns = (entity as EntityObject).GetPK();284 List
arguments = new List();285 StringBuilder builder = new StringBuilder();286 287 foreach (var change in table)288 {289 if (change == primaryKeyColumns)290 continue;291 292 if (arguments.Count != 0)293 builder.Append(", ");294 295 if (change.GetValue(entity, null) != null)296 {297 builder.Append(change.Name + " = { " + arguments.Count + "}");298 arguments.Add(change.GetValue(entity, null));299 }300 else301 {302 builder.Append(change.Name + " = NULL, ");303 }304 }305 306 if (builder.Length == 0)307 return;308 309 builder.Insert(0, "UPDATE " + string.Format("[{0}]", entityType.Name) + " SET ");310 311 builder.Append(" WHERE ");312 bool firstPrimaryKey = true;313 314 foreach (var primaryField in table)315 {316 if (firstPrimaryKey)317 firstPrimaryKey = false;318 else319 builder.Append(" AND ");320 321 object val = entityType.GetProperty(primaryField.Name).GetValue(entity, null);322 builder.Append(GetEqualStatment(primaryField.Name, arguments.Count));323 arguments.Add(val);324 }325 326 327 328 try329 {330 _db.ExecuteStoreCommand(builder.ToString(), arguments.ToArray());331 }332 catch (Exception)333 {334 throw;335 }336 }337 338 private static string GetEqualStatment(string fieldName, int paramId)339 {340 return string.Format("{0} = {1}", fieldName, GetParamTag(paramId));341 342 }343 344 private static string GetParamTag(int paramId)345 {346 return "{ " + paramId + "}";347 348 }349 #endregion350 351 }352 353 354 /// 355 /// ObjectContext扩展356 /// 357 public static class ObjectContextExtension358 {359 /// 360 /// 得到主键361 /// 362 public static PropertyInfo GetPK(this EntityObject value)363 {364 PropertyInfo[] properties = value.GetType().GetProperties();365 foreach (PropertyInfo pI in properties)366 {367 System.Object[] attributes = pI.GetCustomAttributes(true);368 foreach (object attribute in attributes)369 {370 if (attribute is EdmScalarPropertyAttribute)371 {372 if ((attribute as EdmScalarPropertyAttribute).EntityKeyProperty && !(attribute as EdmScalarPropertyAttribute).IsNullable)373 return pI;374 }375 376 }377 }378 return null;379 }380 381 /// 382 /// 把所有属性都标为已修改383 /// 384 /// 385 /// 386 public static void SetAllModified
(this ObjectContext objectContext, TEntity item)387 {388 ObjectStateEntry stateEntry = objectContext.ObjectStateManager.GetObjectStateEntry(item) as ObjectStateEntry;389 IEnumerable propertyNameList = stateEntry.CurrentValues.DataRecordInfo.FieldMetadata.Select(pn => pn.FieldType.Name);390 foreach (string propName in propertyNameList)391 {392 stateEntry.SetModifiedProperty(propName);393 }394 stateEntry.SetModified();395 }396 }397 398 399 400 }

这一个规范,两个实现,在我们实际开发过程中,如果出现问题,请及时与我联系!

大家一起讨论,共同进步!

转载于:https://www.cnblogs.com/lori/archive/2012/10/19/2731801.html

你可能感兴趣的文章
[20151021]理解dbms_xplan.display_cursor的format参数all.txt
查看>>
Unicode字符编码标准
查看>>
云计算就像是产业链的重新组合
查看>>
第三代北斗芯片发布 2020年北斗计划向全球提供服务
查看>>
阿里巴巴集团CTO王坚:云计算让理想平等
查看>>
《中国人工智能学会通讯》——11.30 深度迁移学习
查看>>
Dell EMC扩充数据保护产品线 Data Domain增强云分层功能
查看>>
美柚社区精选:贴心宝妈的八大育儿经验
查看>>
走进医疗明星企业之北京天坛普华医院
查看>>
一点资讯电影贴片广告以假乱真
查看>>
曙光出炉“数据中国加速计划”
查看>>
中国制造2025新机遇 机器视觉行业爆发
查看>>
中国工商银行阿根廷分行用数据运营展现本地特色
查看>>
使用闪存存储的优势与注意事项
查看>>
网络钓鱼防不胜防:大型科技公司竟被骗逾1亿美元
查看>>
网络间谍活动月光迷宫已演变成Turla
查看>>
欧洲运营商展开5GTango项目 应对特定行业市场
查看>>
Windows 10创作者更新将改进蓝牙功能
查看>>
睿联嘉业边缘融合大屏幕多媒体会议系统方案
查看>>
凯立德货车专用导航 应“运”而生
查看>>