有關Entity Framework的數據模型的操作

初次學習EF的時候,在網上收集了不少資料,但很少有對EF系統的介紹和例子,比如如何通過EF對實體模型進行AMD.這使得我不得不自己去研究和實驗,通過反覆的測試,總算摸索了一些方法,今天把代碼粘貼出來以供大家指點和批評。
public interface IOperate<TEntity>
    {
        #region 屬性

        /// <summary>
        ///     獲取 當前實體的查詢數據集
        /// </summary>
        IQueryable<TEntity> Entities { get; }

        #endregion


        void Dispose();
        #region 新  增

        /// <summary>
        /// 新增一條數據
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        int Insert(TEntity entities);

        /// <summary>
        /// 添加一條記錄並返回實體
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        TEntity InsertAndLoadTEntity(TEntity entity);
        /// <summary>
        /// 新增多條記錄
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        int InsertRange(IEnumerable<TEntity> entities);
        #endregion

        #region 修  改
        /// <summary>
        /// 修改整個實體
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        int Update(TEntity entity);

        /// <summary>
        /// 根據表達式參數,按需修改實體
        /// </summary>
        /// <param name="propertyExpression"></param>
        /// <returns></returns>
        int Update(Expression<Func<TEntity, TEntity>> propertyExpression);

        /// <summary>
        /// 根據條件修改(***擴展方法***)
        /// </summary>
        /// <param name="filterExpression"></param>
        /// <param name="updateExpression"></param>
        /// <returns></returns>
        int Update(Expression<Func<TEntity, bool>> filterExpression, Expression<Func<TEntity, TEntity>> updateExpression);

        #endregion

        #region 刪  除

        /// <summary>
        /// 根據條件刪除數據(***擴展方法***)
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        int Delete(Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        /// 刪除實體,只需要主鍵
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        int Delete(TEntity entity);

       /// <summary>
       /// 刪除多條記錄
       /// </summary>
       /// <param name="entities"></param>
       /// <returns></returns>
        int DeleteRange(IEnumerable<TEntity> entities);
        #endregion

        #region 執行語句

        int ExecuteSqlCommand(string sql, object[] paras);

        List<TEntity> SqlQuery(string queryCmdStr, object[] paras);


        #endregion
  

---------------------------------------------以下爲實現接口類--------------------------------------

 public class EfOperate<TEntity> : IOperate<TEntity> where TEntity : class, new()
    {
        private readonly string _dbContextString;
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="dbContext"></param>
        public EfOperate(string dbContext)
        {
            _dbContextString = dbContext;
        }

        private DbContext _dbContext;

        /// <summary>
        /// 獲得數據庫鏈接的上下文
        /// </summary>
        public DbContext GetContext
        {
            get
            {
    //這裏說明一下,爲什麼Dispose()後,又要設置爲Null,因爲Dispose後,實例並沒有變爲Null,這樣再下一次使用時,無法又要重新實例化。

                if (_dbContext == null)
                {
                    if (string.IsNullOrEmpty(_dbContextString))
                        throw new Exception("傳入的DbConnect爲Null");
                    _dbContext= DbContexts.GetDbContext(_dbContextString);

                }
                return _dbContext;
            }
        }

        public void Dispose()
        {
            if (_dbContext == null) return;
            _dbContext.Dispose();
   //這裏說明一下,爲什麼Dispose()後,又要設置爲Null,因爲Dispose後,實例並沒有變爲Null,爲了讓實例不再重新實例化特設置爲Null。結合獲取_dbContext實例看更直觀些。
            _dbContext = null;
        }

        #region 集  合
      
        public IQueryable<TEntity> Entities
        {
            get
            {
                return GetContext.Set<TEntity>();//此時EF還沒有去真正的執行Sql語句,當ToList()的時候纔會把翻譯成sql語句(也即select)去操作數據庫
            }
        }

        #endregion

        #region 添  加
        public int Insert(TEntity entity)
        {
          
            GetContext.Set<TEntity>().Add(entity);
            int rtnNumber= GetContext.SaveChanges();
            Dispose();
            return rtnNumber;
        }

        public TEntity InsertAndLoadTEntity(TEntity entity)
        {

            EntityState state = GetContext.Entry(entity).State;
            if (state == EntityState.Detached)
            {
                GetContext.Entry(entity).State = EntityState.Added;
            }
            GetContext.SaveChanges();
            Dispose();
            return entity;
        }

        /// <summary>
        /// 添加多條記錄
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public int InsertRange(IEnumerable<TEntity> entities)
        {
            try
            {

                GetContext.Set<TEntity>().AddRange(entities);
                int rtnNumber = GetContext.SaveChanges();
    // _dbContext.Dispose()後,實例並沒有變爲Null,
                Dispose();
                return rtnNumber;
            }
            catch (Exception error)
            {
                throw new Exception(error.Message);
            }

        }


        #endregion

        #region 修  改
        /// <summary>
        /// 缺點:必須在從數據庫加載後的基礎上修改,而不能對一個new的對象進行修改(即便設置了主鍵)
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int Update(TEntity entity)
        {
            var entry = GetContext.Entry(entity);
            if (entry.State == EntityState.Detached)
            {
                GetContext.Set<TEntity>().Attach(entity);
                entry.State = EntityState.Modified;
            }
            int rtnNumber = GetContext.SaveChanges();
            Dispose();
            return rtnNumber;

        }
        /// <summary>
        /// 優點:不需要從數據庫中再加載一次,可對部分字段修改;
        /// 缺點:必須設置此數據的主鍵值,否則系統報錯
        /// 例子:UpdateUserPart(o=>new Sys_User{Id=user.Id, Code = user.Code,PreIpAddress = user.PreIpAddress});
        /// </summary>
        /// <param name="propertyExpression"></param>
        /// <returns></returns>
        public int Update(Expression<Func<TEntity, TEntity>> propertyExpression)
        {
            try
            {
                var memberInitExpression = propertyExpression.Body as MemberInitExpression;
                var entity = EntityHelper.CopyPropertyValue(propertyExpression);
                DbEntityEntry<TEntity> entry = GetContext.Entry(entity);
                    entry.State = EntityState.Unchanged;
                if (memberInitExpression != null)
                    foreach (var memberInfo in memberInitExpression.Bindings)
                    {
                        string propertyName = memberInfo.Member.Name;
                        entry.Property(propertyName).IsModified = true;
                    }
                GetContext.Configuration.ValidateOnSaveEnabled = false;
            }
            finally
            {
                GetContext.Configuration.AutoDetectChangesEnabled = true;
            }
            int rtnNumber = GetContext.SaveChanges();
            Dispose();
            return rtnNumber;
        }
        /// <summary>
        /// 修改-擴展方法
        /// 可根據條件修改多條記錄的部分字段
        /// _provider.Update(o =>o.Password.EndsWith("DDD"),o=>new Sys_User{Code = "RDTS"});
        /// 表示滿足Password字段以DDD結尾的記錄,修改其字段Code的值爲傳遞過來的RDTS
        /// </summary>
        /// <param name="filterExpression">要修改的記錄的條件表達式,若直接爲true,則表示全部滿足要修改的記錄</param>
        /// <param name="updateExpression">要修改的部分字段表達式</param>
        /// <returns></returns>
        public int Update(Expression<Func<TEntity, bool>> filterExpression, Expression<Func<TEntity, TEntity>> updateExpression)
        {
            int rtnNumber = GetContext.Set<TEntity>().Where(filterExpression).Update(updateExpression);
            Dispose();
            return rtnNumber;
        }

        #endregion

        #region 刪  除

        public int Delete(TEntity entity)
        {
            #region 方法1 已測試  直接刪除,優點:使用任何類,把記錄直接添加到上下文中,當Remove時會把狀態自動改爲Deleted
            #if ceshi
                        DbContextTransaction transaction = null;
                        try
                        {
                            using (var context = GetContext)
                            {
                                using (transaction = context.Database.BeginTransaction())
                                {
                                    //if (_module.Set<TEntity>().Any(o => o.Id == entity.Id))
                                    //{
                                    context.Set<TEntity>().Attach(entity);
                                    context.Set<TEntity>().Remove(entity);
                                    int rtnNumber = context.SaveChanges();
                                    transaction.Commit();
                                    return rtnNumber;
                                    //}
                                    //return 0;
                                }
                            }
                        }
                        catch (Exception error)
                        {
                            if (transaction != null)
                                transaction.Rollback();
                            throw new Exception(error.Message);
                        }
            #endif
            #endregion


            GetContext.Configuration.AutoDetectChangesEnabled = false;
            DbEntityEntry<TEntity> entry = GetContext.Entry(entity);
            GetContext.Configuration.ValidateOnSaveEnabled = false;
            entry.State = EntityState.Deleted;
            GetContext.Configuration.AutoDetectChangesEnabled = true;
            int rtnNumber = GetContext.SaveChanges();
            Dispose();
            return rtnNumber;


        }
        /// <summary>
        /// 刪除-擴展方法
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public int Delete(Expression<Func<TEntity, bool>> predicate)
        {
            int rtnNumber = GetContext.Set<TEntity>().Where(predicate).Delete();
            Dispose();
            return rtnNumber;
           
        }


        /// <summary>
        /// 刪除多條記錄
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public int DeleteRange(IEnumerable<TEntity> entities)
        {
            try
            {
                foreach (var entity in entities)
                {
                    var entry = GetContext.Entry(entity);
                    if (entry.State == EntityState.Detached)
                    {
                        entry.State = EntityState.Deleted;
                    }
                }
                int rtnNumber = GetContext.SaveChanges();
                Dispose();
                return rtnNumber;

            }
            catch (Exception error)
            {
                throw new Exception(error.Message);
            }

        }
        #endregion

        #region 執行語句

        public int ExecuteSqlCommand(string sql, object[] paras)
        {
            DbContextTransaction transaction = null;
            try
            {

                using (transaction = GetContext.Database.BeginTransaction())
                {

                    int rtnNUmber = paras == null
                        ? GetContext.Database.ExecuteSqlCommand(sql)
                        : GetContext.Database.ExecuteSqlCommand(sql, paras);
                    GetContext.SaveChanges();
                    transaction.Commit();
                    Dispose();
                    return rtnNUmber;
                }
              
            }
            catch (Exception error)
            {
                if (transaction != null)
                    transaction.Rollback();
                throw new Exception("數據執行時發生異常:" + error.Message);
            }
         

        }

        public List<TEntity> SqlQuery(string queryCmdStr, object[] paras)
        {
          
            try
            {
                var lists= paras == null
                    ? GetContext.Database.SqlQuery<TEntity>(queryCmdStr).ToList()
                    : GetContext.Database.SqlQuery<TEntity>(queryCmdStr, paras).ToList();
                Dispose();
                return lists;
            }
            catch (Exception error)
            {
                throw new Exception(error.Message);
            }

        }

        #endregion
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章