zoukankan      html  css  js  c++  java
  • 通用EF框架

    之前我老大去网上找了一个DAL里面操作数据库的通用类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    public class DALHelper
    {
        public static List<T> Search<T>() where T : SH_SetBase
        {
            using (var db = new ShopContext())
            {
                var dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    return dbSet.Where(o => !o.IsDelete).ToList();
                }
                return dbSet.ToList();
            }
        }
     
        public static List<T> Search<T>(Expression<Func<T, bool>> wherewhere T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    return dbSet.Where(where3.Compile()).ToList();
                }
                return dbSet.Where(where).ToList();
            }
        }
     
        public static List<T> Search<T>(Expression<Func<T, bool>> where, PageContent pageContent) where T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    where = where3;
                }
                pageContent.TotalLogs = Count<T>(where);
                return dbSet.Where(where.Compile()).Skip((pageContent.PageIndex - 1) * pageContent.PageSize).Take(pageContent.PageSize).ToList();
            }
        }
     
        public static List<T> Search<T>(Expression<Func<T, object>> include, Expression<Func<T, bool>> wherewhere T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    return dbSet.Include(include).Where(where3.Compile()).ToList();
                }
                return dbSet.Include(include).Where(where).ToList();
            }
        }
     
        public static List<T> Search<T>(Expression<Func<T, object>> include, Expression<Func<T, bool>> where, PageContent pageContent) where T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    where = where3;
                }
                pageContent.TotalLogs = Count<T>(where);
                return dbSet.Include(include).Where(where.Compile()).Skip((pageContent.PageIndex - 1) * pageContent.PageSize).Take(pageContent.PageSize).ToList();
            }
        }
     
        public static List<T> Search<T>(Expression<Func<T, bool>> where, PageContent pageContent, Expression<Func<T, object>> order, bool isAsc) where T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    where = where3;
                }
                pageContent.TotalLogs = Count<T>(where);
                if (isAsc)
                    return dbSet.Where(where.Compile()).OrderBy(order.Compile()).Skip((pageContent.PageIndex - 1) * pageContent.PageSize).Take(pageContent.PageSize).ToList();
                else
                    return dbSet.Where(where.Compile()).OrderByDescending(order.Compile()).Skip((pageContent.PageIndex - 1) * pageContent.PageSize).Take(pageContent.PageSize).ToList();
            }
        }
     
        public static List<T> Search<T>(Expression<Func<T, object>> include, Expression<Func<T, bool>> where, PageContent pageContent, Expression<Func<T, object>> order, bool isAsc) where T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    where = where3;
                }
                pageContent.TotalLogs = Count<T>(where);
                if (isAsc)
                    return dbSet.Include(include).Where(where.Compile()).OrderBy(order.Compile()).Skip((pageContent.PageIndex - 1) * pageContent.PageSize).Take(pageContent.PageSize).ToList();
                else
                    return dbSet.Include(include).Where(where.Compile()).OrderByDescending(order.Compile()).Skip((pageContent.PageIndex - 1) * pageContent.PageSize).Take(pageContent.PageSize).ToList();
            }
        }
     
        public static List<T> Search<T>(Expression<Func<T, object>> path1, Expression<Func<T, object>> path2, Expression<Func<T, bool>> where, PageContent pageContent, Expression<Func<T, object>> order, bool isAsc) where T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    where = where3;
                }
                pageContent.TotalLogs = Count<T>(where);
                if (isAsc)
                    return dbSet.Include(path1).Include(path2).Where(where.Compile()).OrderBy(order.Compile()).Skip((pageContent.PageIndex - 1) * pageContent.PageSize).Take(pageContent.PageSize).ToList();
                else
                    return dbSet.Include(path1).Include(path2).Where(where.Compile()).OrderByDescending(order.Compile()).Skip((pageContent.PageIndex - 1) * pageContent.PageSize).Take(pageContent.PageSize).ToList();
            }
        }
     
        public static bool Exist<T>(Expression<Func<T, bool>> wherewhere T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    return dbSet.FirstOrDefault(where3.Compile()) != null;
                }
                return dbSet.FirstOrDefault(where.Compile()) != null;
            }
        }
     
        public static int Count<T>(Expression<Func<T, bool>> wherewhere T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    return dbSet.Count(where3.Compile());
                }
                return dbSet.Count(where);
            }
        }
     
        public static decimal Sum<T>(Expression<Func<T, bool>> where, Expression<Func<T, decimal>> selector) where T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    return dbSet.Where(where3.Compile()).Sum(selector.Compile());
                }
                return dbSet.Where(where.Compile()).Sum(selector.Compile());
            }
        }
     
        public static int Sum<T>(Expression<Func<T, bool>> where, Expression<Func<T, int>> selector) where T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    return dbSet.Where(where3.Compile()).Sum(selector.Compile());
                }
                return dbSet.Where(where.Compile()).Sum(selector.Compile());
            }
        }
     
        public static T SearchObject<T>(Expression<Func<T, bool>> wherewhere T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    Expression<Func<T, bool>> where2 = (o => (o as SH_SetBase).IsDelete == false);
                    var invokedExpr = Expression.Invoke(where2, where.Parameters.Cast<Expression>());
                    Expression<Func<T, bool>> where3 = Expression.Lambda<Func<T, bool>>(Expression.And(where.Body, invokedExpr), where.Parameters);
                    return dbSet.FirstOrDefault(where3.Compile());
                }
                return dbSet.FirstOrDefault(where.Compile());
            }
        }
     
        public static T Find<T>(long id) where T : SH_Base
        {
            using (ShopContext db = new ShopContext())
            {
                DbSet<T> dbSet = GetDBSet(db, typeof(T)) as DbSet<T>;
                if (typeof(T).IsSubclassOf(typeof(SH_SetBase)))
                {
                    SH_SetBase model = dbSet.Find(id) as SH_SetBase;
                    if (model != null && !model.IsDelete)
                        return model as T;
                }
                return dbSet.Find(id) as T;
            }
        }
     
        public static bool Save(SH_Base model)
        {
            using (ShopContext db = new ShopContext())
            {
                object dbSet = GetDBSet(db, model);
                if (model.ID == 0)
                {
                    CallMethod(dbSet, "Add"new object[] { model });
                }
                else
                {
                    CallMethod(dbSet, "Attach"new object[] { model });
                    db.Entry(model).State = EntityState.Modified;
                }
                if (model.GetType().IsSubclassOf(typeof(SH_SetBase)))
                {
                    ((SH_SetBase)model).LastUpdateTime = DateTime.Now;
                    ((SH_SetBase)model).IsDelete = false;
                }
                else
                {
                    ((SH_LogBase)model).LogTime = DateTime.Now;
                }
                db.SaveChanges();
                return true;
            }
        }
     
        public static bool Delete(SH_Base model)
        {
            using (ShopContext db = new ShopContext())
            {
                if (model.GetType().IsSubclassOf(typeof(SH_SetBase)))
                {
                    ((SH_SetBase)model).LastUpdateTime = DateTime.Now;
                    ((SH_SetBase)model).IsDelete = true;
                    db.Entry(model).State = EntityState.Modified;
                    db.SaveChanges();
                    return true;
                }
     
                object dbSet = GetDBSet(db, model);
                CallMethod(dbSet, "Remove"new object[] { model });
                db.Entry(model).State = EntityState.Modified;
                db.SaveChanges();
                return true;
            }
        }
     
        private static object GetDBSet(ShopContext db, SH_Base model)
        {
            string modelName = ObjectContext.GetObjectType(model.GetType()).Name;
            modelName = modelName.Replace("SH_""");
            Type type = db.GetType();
            PropertyInfo property = type.GetProperty(modelName);
            object dbSet = property.GetValue(db);
            return dbSet;
        }
     
        private static object GetDBSet(ShopContext db, Type type)
        {
            type = ObjectContext.GetObjectType(type);
            string modelName = type.Name;
            modelName = modelName.Replace("SH_""");
            PropertyInfo property = db.GetType().GetProperty(modelName);
            object dbSet = property.GetValue(db);
            return dbSet;
        }
     
        private static object CallMethod(object obj, string methodName, object[] parms)
        {
            Type type = obj.GetType();
            MethodInfo methodInfo = type.GetMethod(methodName);
            return methodInfo.Invoke(obj, parms);
        }
    }

      可以看到里面包含了对SH_SetBase的特殊处理,这个有必要解释一下,因为老大之前的设计是数据库表分为两类,一种是记录表(日志表),他们继承自SH_LogBase,一种是姑且说是对象表吧,他们继承自SH_SetBase,然后全部表继承自SH_Base表,为什么要这样设计呢,其中一个原因是对象表里的数据不能真删除,他们一般是有外键的,级联删除的话删除太多了,而且里面的数据也很重要,只能假删除,所以SH_SetBase得有是否删除IsDelete字段,假删除的话那部分数据是不会再取出来的,除了假删除应该还可以禁用,比如冻结账号,冻结后又可以解冻,这就需要是否启用字段IsEnable字段。

      SH_Base表:

    复制代码
        public class SH_Base
        {
             /// <summary>
            /// 标识,自动增加
             /// </summary>
            [Key]
            public long ID
            {
                get;
                set;
            }
    
            /// <summary>
            /// 备注
            /// </summary>
            [Display(Name = "备注")]
            public string Summary
            {
                get;
                set;
            }
        }
    复制代码

      SH_LogBase表:

    复制代码
        public class SH_LogBase : SH_Base
        {
            private DateTime _logTime = DateTime.Now;
    
            /// <summary>
            /// 记录时间,默认当前时间
            /// </summary>
            [Display(Name = "记录时间")]
            public DateTime LogTime
            {
                get { return _logTime; }
                set { _logTime = value; }
            }
        }
    复制代码

      SH_SetBase表:

    复制代码
        public class SH_SetBase : SH_Base
        {
            /// <summary>
            /// 是否删除,默认未删除
            /// </summary>
            [Display(Name = "是否删除")]
            public bool IsDelete
            {
                get;
                set;
            }
    
            private bool _isEnable = true;
    
            /// <summary>
            /// 是否启用,默认为启用
            /// </summary>
            [Display(Name = "是否启用")]
            public bool IsEnable
            {
                get { return _isEnable; }
                set { _isEnable = value; }
            }
    
            private DateTime _lastUpdateTime = DateTime.Now;
    
            /// <summary>
            /// 最后更新时间,默认当前时间
            /// </summary>
            [Display(Name = "最后更新时间")]
            public DateTime LastUpdateTime
            {
                get { return _lastUpdateTime; }
                set { _lastUpdateTime = value; }
            }
        }
    复制代码

      可我发觉DalHelper太臃肿了,而且里面用到了反射,我一直避免用反射,觉得那货效率比较低。后来看了C#线程内唯一的单例用法。把DalHelper拆分成两个BaseDal和SetBaseDal类,他们继承自IBaseDal类,里面的数据库采用线程内单例模式:

    复制代码
        public class DbContextFactory
        {
            public static ShopContext GetCurrentDbContext()
            {
                var db = (ShopContext)CallContext.GetData("ShopContext");  //CallContext是一个可提供类似于HashTable的Key-Value键值对存储的缓存对象。

    //使用方法:

    //1.存储:使用CallContext.SetData(string,object)方法指定缓存指定的对象。

    //2.取值:使用CallContext.GetData(string)方法来获取缓存中指定的对象。

    //3.清除:使用CallContext.FreeNamedDataSlot(string)方法来移除缓存中指定的对象。


    if (db != null) return db; db = new ShopContext(); CallContext.SetData("ShopContext", db); return db; } }
    复制代码

      或许有些同志会好奇线程内单例模式有什么好处或者什么用,我这里简单做个测试:

    复制代码
            public static ShopContext GetCurrentDbContext()
            {
                //单例模式:保证线程实例唯一
                var db = (ShopContext)CallContext.GetData("ShopContext");
                if (db != null)
                {
                    File.AppendAllText("E:\ShopDb.txt", Thread.CurrentThread.ManagedThreadId + "旧");
                    return db;
                }
                File.AppendAllText("E:\ShopDb.txt", Environment.NewLine + Thread.CurrentThread.ManagedThreadId + "新");
                db = new ShopContext();
                CallContext.SetData("ShopContext", db);
                return db;
            }
    复制代码

      然后运行网站程序,随便乱点打开ShopDb.txt一看

    可以看出我每点一次网页链接,控制器的Action接收到请求后就会新建一个线程来处理这次请求,由于我在该线程内一直没有另开线程,所以看到的生成的文件内每次请求就会产生一个新的ShopContext,在单次网页请求内用的都是同一个ShopContext的,这样你可能会说有问题呀,单次网页请求共用一个ShopContext,要是某次数据库请求太耗时,难道后续的操作要一直等待吗,这个问题确实存在,解决的办法就是数据库请求采用异步请求,单个线程共用ShopContext有个好处就是单次请求内只需新建一次ShopContext,不用老在内存中新建这个对象,这样的话可能你会说像线程池一样,搞个ShopContext池不是更好吗,线程要的时候去池中取一个ShopContext出来,不用的时候归还给池,这样ShopContext在内存中新建销毁的次数就可以达到最少次数了,这个我就不研究下去了。

      接口IBaseDal类:

    复制代码
        interface IBaseDal<T>
        {
            T Find(long id);
            T First(Expression<Func<T, bool>> predicate);
            T Add(T entity);
            bool Update(T entity);
            bool Delete(long id);
            bool Delete(T entity);
            bool Delete(IEnumerable<T> entities);
            bool Exist(Expression<Func<T, bool>> predicate);
            int Count(Expression<Func<T, bool>> predicate);
            int Sum(Expression<Func<T, bool>> predicate, Expression<Func<T, int>> selector);
            decimal Sum(Expression<Func<T, bool>> predicate, Expression<Func<T, decimal>> selector);
            IQueryable<T> LoadEntities();
            IQueryable<T> LoadEntities(Expression<Func<T, bool>> predicate);
            IQueryable<T> LoadPageEntities<TS>(PageContent page, Expression<Func<T, bool>> predicate,
                Expression<Func<T, TS>> keySelector, bool isAsc);
        }
    复制代码

      日志类使用的BaseDal类:

    复制代码
        public class BaseDal<T> : IBaseDal<T> where T : class , new()
        {
            public static ShopContext Db
            {
                get
                {
                    return DbContextFactory.GetCurrentDbContext();
                }
            }
    
            public virtual T Find(long id)
            {
                return Db.Set<T>().Find(id);
            }
    
            public virtual T First(Expression<Func<T, bool>> predicate)
            {
                return Db.Set<T>().FirstOrDefault(predicate);
            }
    
            public virtual T Add(T entity)
            {
                Db.Set<T>().Add(entity);
                return entity;
            }
    
            public virtual bool Update(T entity)
            {
                Db.Entry(entity).State = EntityState.Modified;
                return true;
            }
    
            public virtual bool Delete(long id)
            {
                return Delete(Find(id));
            }
    
            public virtual bool Delete(T entity)
            {
                Db.Set<T>().Remove(entity);
                return true;
            }
    
            public virtual bool Delete(IEnumerable<T> entities)
            {
                Db.Set<T>().RemoveRange(entities);
                return true;
            }
    
            public virtual bool Exist(Expression<Func<T, bool>> predicate)
            {
                return Db.Set<T>().Any(predicate);
            }
    
            public virtual int Count(Expression<Func<T, bool>> predicate)
            {
                return Db.Set<T>().Count(predicate);
            }
    
            public virtual int Sum(Expression<Func<T, bool>> predicate, Expression<Func<T, int>> selector)
            {
                try
                {
                    return Db.Set<T>().Where(predicate).Sum(selector);
                }
                catch
                {
                    return 0;
                }
            }
    
            public virtual decimal Sum(Expression<Func<T, bool>> predicate, Expression<Func<T, decimal>> selector)
            {
                try
                {
                    return Db.Set<T>().Where(predicate).Sum(selector);
                }
                catch
                {
                    return 0;
                }
            }
    
            public virtual IQueryable<T> LoadEntities()
            {
                return Db.Set<T>().AsQueryable();
            }
    
            public virtual IQueryable<T> LoadEntities(Expression<Func<T, bool>> predicate)
            {
                return Db.Set<T>().Where(predicate);
            }
    
            public virtual IQueryable<T> LoadPageEntities<TS>(PageContent page, Expression<Func<T, bool>> predicate, Expression<Func<T, TS>> keySelector, bool isAsc)
            {
                page.TotalItems = Count(predicate);
                var lst = Db.Set<T>().Where(predicate);
                lst = isAsc ? lst.OrderBy(keySelector) : lst.OrderByDescending(keySelector);
                return lst.Skip(page.PageSize * (page.PageIndex - 1))
                      .Take(page.PageSize);
            }
        }
    复制代码

      对象类使用的SetBaseDal类:

    复制代码
        public class SetBaseDal<T> : IBaseDal<T> where T : SH_SetBase, new()
        {
            public static ShopContext Db
            {
                get
                {
                    return DbContextFactory.GetCurrentDbContext();
                }
            }
    
            public virtual T Find(long id)
            {
                var t = Db.Set<T>().Find(id);
                return t.IsDelete ? null : t;
            }
    
            public virtual T First(Expression<Func<T, bool>> predicate)
            {
                return Db.Set<T>().Where(o => !o.IsDelete).FirstOrDefault(predicate);
            }
    
            public virtual T Add(T entity)
            {
                Db.Set<T>().Add(entity);
                return entity;
            }
    
            public virtual bool Update(T entity)
            {
                entity.LastUpdateTime = DateTime.Now;
                Db.Entry(entity).State = EntityState.Modified;
                return true;
            }
    
            public virtual bool Delete(long id)
            {
                return Delete(Find(id));
            }
    
            public virtual bool Delete(T entity)
            {
                entity.IsDelete = true;
                entity.LastUpdateTime = DateTime.Now;
                Db.Entry(entity).State = EntityState.Modified;
                return true;
            }
    
            public virtual bool Delete(IEnumerable<T> entities)
            {
                foreach (var entity in entities)
                {
                    Delete(entity);
                }
                return true;
            }
    
            public virtual bool Exist(Expression<Func<T, bool>> predicate)
            {
                return Db.Set<T>().Where(o => !o.IsDelete).Any(predicate);
            }
    
            public virtual int Count(Expression<Func<T, bool>> predicate)
            {
                return Db.Set<T>().Where(o => !o.IsDelete).Count(predicate);
            }
    
            public virtual int Sum(Expression<Func<T, bool>> predicate, Expression<Func<T, int>> selector)
            {
                try
                {
                    return Db.Set<T>().Where(predicate).Where(o => !o.IsDelete).Sum(selector);
                }
                catch
                {
                    return 0;
                }
            }
    
            public virtual decimal Sum(Expression<Func<T, bool>> predicate, Expression<Func<T, decimal>> selector)
            {
                try
                {
                    return Db.Set<T>().Where(predicate).Where(o => !o.IsDelete).Sum(selector);
                }
                catch
                {
                    return 0;
                }
            }
    
            public virtual IQueryable<T> LoadEntities()
            {
                return Db.Set<T>().Where(o => !o.IsDelete);
            }
    
            public virtual IQueryable<T> LoadEntities(Expression<Func<T, bool>> predicate)
            {
                return Db.Set<T>().Where(predicate).Where(o => !o.IsDelete);
            }
    
            public virtual IQueryable<T> LoadPageEntities<TS>(PageContent page, Expression<Func<T, bool>> predicate, Expression<Func<T, TS>> keySelector, bool isAsc)
            {
                page.TotalItems = Count(predicate);
                var lst = Db.Set<T>()
                    .Where(predicate)
                    .Where(o => !o.IsDelete);
                lst = isAsc ? lst.OrderBy(keySelector) : lst.OrderByDescending(keySelector);
                return lst.Skip(page.PageSize * (page.PageIndex - 1))
                      .Take(page.PageSize);
            }
        }
    复制代码

      里面还有个PageContent类:

    复制代码
        public class PageContent
        {
            public int PageIndex { get; set; }
    
            public int PageSize { get; set; }
    
            public int TotalItems { get; set; }
    
            public int TotalPages
            {
                get
                {
                    if (PageSize == 0) return 0;
                    return (TotalItems + PageSize - 1)/PageSize;
                }
            }
        }
    复制代码

      可以看出BaseDal和SetBaseDal之间最大的区别就是BaseDal删除是真删除,SetBaseDal不能真删除,调用删除方法自动执行假删除,而且SetBaseDal获取数据等所有方法都把假删除的数据排除掉了。可能你会问既然假删除的数据都被排除掉了,那他们还有存在的必要吗,当然有必要了,因为除了用户看这些数据,管理人员是可以直接去数据库看的,那就能看到那些被假删除的数据了。

      写好这BaseDal和SetBaseDal类之后,BLL的类就可以继承自这两个类或者不继承,在类里使用者两个类,设计理念我不在行,貌似不建议直接继承Dal的通用类,而是在BLL定义一个接口,然后实现每个表的该接口,并在该类里引用Dal里的通用类,不过我觉得怎么方便就怎么用吧,何必一定要符合设计理念呢。还有贫血模型也是,按照面向对象理念是不能设计为贫血模型的,因为一个对象必须是完整的,里面的属性就像一个对象的血肉肢体,而里面的方法就像一个对象能够进行的活动,缺少了方法的实体类就像是尸体类,光有肢体不能动,可我还是那句话,怎么方便就怎么用吧,为何一定要面向对象呢,而且我认为光有属性也有好处,当我只需要该对象来传值的时候其实是不需要该对象的行为的,这样的话贫血模型加载到内存中占用的内存就少了些了。当然,这只是我的胡言乱语,大神请直接忽视。。。

  • 相关阅读:
    转载 轻松搞定面试中的二叉树题目
    关于AVplayer 缓冲问题的处理
    关于iOS接收到推送消息后跳转问题
    iOS 黑魔法
    UITableView的优化
    OC是动态运行时语言是什么意思?什么是动态识别,动态绑定?
    iOS深复制和浅复制
    iOS内存管理(ARC,MRC)
    iOS数据持久化
    详解KVO,KVC
  • 原文地址:https://www.cnblogs.com/sjqq/p/7001215.html
Copyright © 2011-2022 走看看