在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 IQueryableGetEntities () 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 }
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
这一个规范,两个实现,在我们实际开发过程中,如果出现问题,请及时与我联系!
大家一起讨论,共同进步!