最近看了很多网络上面的很多人写的数据库底层,所以就复制和整理了他们的代码自己拼凑了一个,特意写下了来,希望看到博客的大哥们给提点意见。因为感觉写完以后思路很乱。
代码结构如下
SimpleDbContext,SimpleDbContext : DbContext,ISimpleDbContext
DbRepository,DbRepository<T> : IDbRepository<T> where T : class
UnitOfWork ,UnitOfWork : IUnitOfWork
在项目的逻辑层 我打算使用UnitOfWork,UnitofWork有方法可以获取到所有的Repository对象。但是感觉整体好像是把DBContext 封装成了UnitOfwork,好像是重复的工作一样。所以希望看到博客的
大哥们,可以给我一些修改的建议。非常感谢!
public interface ISimpleDbContext { /// <summary> /// Save changes /// </summary> /// <returns></returns> int SaveChanges(); /// <summary> /// Execute stores procedure and load a list of entities at the end /// </summary> /// <typeparam name="TEntity">Entity type</typeparam> /// <param name="commandText">Command text</param> /// <param name="parameters">Parameters</param> /// <returns>Entities</returns> IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : class, new(); /// <summary> /// Creates a raw SQL query that will return elements of the given generic type. The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type. The type does not have to be an entity type. The results of this query are never tracked by the context even if the type of object returned is an entity type. /// </summary> /// <typeparam name="TElement">The type of object returned by the query.</typeparam> /// <param name="sql">The SQL query string.</param> /// <param name="parameters">The parameters to apply to the SQL query string.</param> /// <returns>Result</returns> IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters); /// <summary> /// Executes the given DDL/DML command against the database. /// </summary> /// <param name="sql">The command string</param> /// <param name="doNotEnsureTransaction">false - the transaction creation is not ensured; true - the transaction creation is ensured.</param> /// <param name="timeout">Timeout value, in seconds. A null value indicates that the default value of the underlying provider will be used</param> /// <param name="parameters">The parameters to apply to the command string.</param> /// <returns>The result returned by the database after executing the command.</returns> int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters); }
public class SimpleDbContext : DbContext,ISimpleDbContext { protected override void OnModelCreating(DbModelBuilder modelBuilder) { var typesToRegister = Assembly.GetExecutingAssembly().GetTypes() .Where(type => !String.IsNullOrEmpty(type.Namespace)) .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)); foreach (var type in typesToRegister) { dynamic configurationInstance = Activator.CreateInstance(type); modelBuilder.Configurations.Add(configurationInstance); } base.OnModelCreating(modelBuilder); } /// <summary> /// Execute stores procedure and load a list of entities at the end /// </summary> /// <typeparam name="TEntity">Entity type</typeparam> /// <param name="commandText">Command text</param> /// <param name="parameters">Parameters</param> /// <returns>Entities</returns> public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : class, new() { //add parameters to command if (parameters != null && parameters.Length > 0) { for (int i = 0; i <= parameters.Length - 1; i++) { var p = parameters[i] as DbParameter; if (p == null) throw new Exception("Not support parameter type"); commandText += i == 0 ? " " : ", "; commandText += "@" + p.ParameterName; if (p.Direction == ParameterDirection.InputOutput || p.Direction == ParameterDirection.Output) { //output parameter commandText += " output"; } } } var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList(); return result; } /// <summary> /// Creates a raw SQL query that will return elements of the given generic type. The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type. The type does not have to be an entity type. The results of this query are never tracked by the context even if the type of object returned is an entity type. /// </summary> /// <typeparam name="TElement">The type of object returned by the query.</typeparam> /// <param name="sql">The SQL query string.</param> /// <param name="parameters">The parameters to apply to the SQL query string.</param> /// <returns>Result</returns> public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters) { return this.Database.SqlQuery<TElement>(sql, parameters); } /// <summary> /// Executes the given DDL/DML command against the database. /// </summary> /// <param name="sql">The command string</param> /// <param name="doNotEnsureTransaction">false - the transaction creation is not ensured; true - the transaction creation is ensured.</param> /// <param name="timeout">Timeout value, in seconds. A null value indicates that the default value of the underlying provider will be used</param> /// <param name="parameters">The parameters to apply to the command string.</param> /// <returns>The result returned by the database after executing the command.</returns> public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters) { int? previousTimeout = null; if (timeout.HasValue) { //store previous timeout previousTimeout = ((IObjectContextAdapter)this).ObjectContext.CommandTimeout; ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = timeout; } var transactionalBehavior = doNotEnsureTransaction ? TransactionalBehavior.DoNotEnsureTransaction : TransactionalBehavior.EnsureTransaction; var result = this.Database.ExecuteSqlCommand(transactionalBehavior, sql, parameters); if (timeout.HasValue) { //Set previous timeout back ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = previousTimeout; } //return result return result; }
public interface IDbRepository<T> where T : class { //基础方法 void Add(T entity); void Delete(System.Linq.Expressions.Expression<Func<T, bool>> where); void Delete(T entity); T GetByKey(object id); System.Linq.IQueryable<T> Table { get; } void Update(T entity); //扩展方法(调用就会立即执行) int DeleteEx(System.Linq.Expressions.Expression<Func<T, bool>> where); int UpdateEx(System.Linq.Expressions.Expression<Func<T, bool>> filterExpression, System.Linq.Expressions.Expression<Func<T, T>> updateExpression); int UpdateEx(System.Linq.Expressions.Expression<Func<T, T>> updateExpression); }
public class DbRepository<T> : IDbRepository<T> where T : class { private SimpleDbContext _DataContext; private IDbSet<T> TModel; public DbRepository(SimpleDbContext db) { _DataContext = db; var objectContext = (_DataContext as IObjectContextAdapter).ObjectContext; objectContext.CommandTimeout = 300; TModel = _DataContext.Set<T>(); } #region 属性 public IQueryable<T> Table { get { return TModel.AsQueryable(); } } public IQueryable<T> TableNoTracking { get { return TModel.AsNoTracking(); } } #endregion #region 基础方法 public virtual T GetByKey(object id) { return TModel.Find(id); } public virtual void Add(T entity) { TModel.Add(entity); } public virtual void Update(T entity) { TModel.Attach(entity); _DataContext.Entry(entity).State = EntityState.Modified; } public virtual void Delete(T entity) { TModel.Remove(entity); } public virtual void Delete(Expression<Func<T, bool>> where) { IEnumerable<T> objects = TModel.Where<T>(where).AsEnumerable(); foreach (T obj in objects) TModel.Remove(obj); } //public virtual int SaveChanges() //{ // try // { // return _DataContext.SaveChanges(); // } // catch (DbEntityValidationException dbEx) // { // var msg = string.Empty; // foreach (var validationErrors in dbEx.EntityValidationErrors) // foreach (var validationError in validationErrors.ValidationErrors) // msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); // var fail = new Exception(msg, dbEx); // throw fail; // } //} #endregion #region 扩展方法,但是操作是直接提交的 需要引用这个EntityFramework.Extensions,Nuget包(EntityFramework.Extended) public int UpdateEx(Expression<Func<T, T>> updateExpression) { return TModel.Update<T>(updateExpression); } public int UpdateEx(Expression<Func<T, bool>> filterExpression, Expression<Func<T, T>> updateExpression) { return TModel.Update(filterExpression, updateExpression); } public int DeleteEx(Expression<Func<T, bool>> where) { return TModel.Delete(where); } #endregion }
public interface IUnitOfWork : IDisposable { int Commit(); IDbRepository<TEntity> GetRepository<TEntity>() where TEntity : class; }
public class UnitOfWork : IUnitOfWork { private SimpleDbContext _simpleDbContext; private Dictionary<Type, object> repositoryCache = new Dictionary<Type, object>(); public UnitOfWork(ISimpleDbContext context) { _simpleDbContext = context as SimpleDbContext; } public int Commit() { try { return _simpleDbContext.SaveChanges(); } catch (DbEntityValidationException dbEx) { var msg = string.Empty; foreach (var validationErrors in dbEx.EntityValidationErrors) foreach (var validationError in validationErrors.ValidationErrors) msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); var fail = new Exception(msg, dbEx); throw fail; } } public void Dispose() { this._simpleDbContext.Dispose(); } public IDbRepository<TEntity> GetRepository<TEntity>() where TEntity : class { if (repositoryCache.ContainsKey(typeof(TEntity))) { return (IDbRepository<TEntity>)repositoryCache[typeof(TEntity)]; } IDbRepository<TEntity> repository = new DbRepository<TEntity>(_simpleDbContext); this.repositoryCache.Add(typeof(TEntity), repository); return repository; } }
时间: 2024-10-17 21:28:01