• DB First 中对Repository 层封装的几点小记


    在数据库表创建完成的情况下,使用DB First 进行开发,封装底层会遇到一些小问题,在此记录一下,供以后参考。

    主要解决的问题有:

    1、EF上下文管理

    2、BaseRepository的封装

    3、EF中实体序列化的问题

    1、EF上下文管理

              EF操作数据库的上下文,要达到在用户每一次的请求操作中都只有一个上下文,当用户通过Http请求结束后要释放用户使用的上下文资源,也就

    是EF生成中的ObjectContext不能每次使用时候通过new 创建一个新的实例,一次请求只需要创建一次,请求结束ObjectContext资源释放。

              这里要用到的就是单例模式和简单工厂了,单例保证只有一个ObjectContext ,每次调用通过工厂方式获取。这里直接贴代码

     1    public class DbContextFactory
     2     {
     3        private static string efKey = "ef_key";
     4 
     5        public static RBACEntities GetContext() 
     6        {
     7            RBACEntities db = CallContext.GetData(efKey) as RBACEntities;
     8            if (db == null) 
     9            {
    10                db = new RBACEntities();
    11                CallContext.SetData(efKey,db);
    12            }
    13            Debug.WriteLine("EF上下文获取:" + db.GetHashCode() + ",时间:" + DateTime.Now.ToString("hh-mm-ss ffff"));
    14            return db;
    15        }
    16 
    17        public static void Dispose() 
    18        {
    19            var context=GetContext();
    20            Debug.WriteLine("EF上下文释放:" + context.GetHashCode() + ",时间:" + DateTime.Now.ToString("hh-mm-ss ffff"));
    21            context.Dispose();
    22        }
    23     }
    View Code

     然后,在Global.asax中,在请求结束事件中调用释放资源方法。

    1        protected void Application_EndRequest()
    2         {
    3             Dedeyi.RBAC2.Core.Model.DbContextFactory.Dispose();
    4         }


         Debug.WriteLine是调试时候,追踪一下上下文的获取和释放是否达到目的。打开调试的Output ,检测到一次请求的输出信息

              

        可以看到,在这次请求处理中使用了两次上下文实例,都是同一个实例(HashCode相同),最后又一次的资源释放。

    2、BaseRepository的封装

            基仓储的封装。要实现基本的增删查改操作。在这里因为使用的是Entity Framework 中的ObjectContext进行数据库交互,其灵活性是很强的

    如果只是像ADO.NET中通过sql对CRUD的封装那样,就很多地方没法发挥ObjectContex的作用了。

            所有我们在基类中要把这个上下文留出来,作为一个可以访问的属性。通过这个上下文,可以在自类中访问数据模型中其他表,ObjectSet 是对应当前EF实体对象,也把这个暴露给外面使用。然后就是分页和搜索的封装了。具体代码如下:

     1  public class BaseRepository<TEntity> where TEntity: EntityObject
     2     {
     3        protected RBACEntities RBACContext { get; set; }
     4        protected ObjectSet<TEntity> DbSet { get; set; }
     5 
     6        protected virtual IQueryable<TEntity> Entities 
     7        {
     8            get { return RBACContext.CreateObjectSet<TEntity>(); }
     9        }
    10 
    11        public BaseRepository() 
    12        {
    13            this.RBACContext = DbContextFactory.GetContext();
    14            this.DbSet=RBACContext.CreateObjectSet<TEntity>();
    15        }
    16 
    17        public IQueryable<TEntity> GetPage<TKey>(int pageIndex, int pageSize,Expression<Func<TEntity,TKey>> orderBy, out int totalRecord) 
    18        {
    19            totalRecord = DbSet.Count();
    20            return  this.DbSet
    21                       .OrderByDescending(orderBy)
    22                       .Skip((pageIndex - 1) * pageSize)
    23                       .Take(pageSize)
    24                       .AsQueryable();
    25        }
    26 
    27        public IQueryable<TEntity> GetPage<TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, Expression<Func<TEntity, bool>> where, out int totalRecord)
    28        {
    29            var res=DbSet.Where(where);
    30 
    31            totalRecord = res.Count();
    32            return  res
    33                       .OrderByDescending(orderBy)
    34                       .Skip((pageIndex - 1) * pageSize)
    35                       .Take(pageSize)
    36                       .AsQueryable();
    37        }
    38 
    39 
    40        public TEntity Add(TEntity entity,bool saveChange) 
    41        {
    42            RBACContext.CreateObjectSet<TEntity>().AddObject(entity);
    43            if (saveChange) 
    44            {
    45                RBACContext.SaveChanges();
    46            }
    47            return entity;
    48        }
    49 
    50        public TEntity Edit(TEntity entity, bool saveChange) 
    51        {
    52            RBACContext.CreateObjectSet<TEntity>().Attach(entity);
    53            RBACContext.ObjectStateManager.ChangeObjectState(entity,System.Data.EntityState.Modified);
    54            if (saveChange) 
    55            {
    56                RBACContext.SaveChanges();
    57            }
    58            return entity;
    59        }
    60 
    61        public void Delete(TEntity entity, bool saveChange) 
    62        {
    63            RBACContext.CreateObjectSet<TEntity>().DeleteObject(entity);
    64            if (saveChange) { RBACContext.SaveChanges(); }
    65        }
    66     }
    View Code

          SaveChange是一个bool 类型参数,表明是否要上下文保存到数据库,如果只是修改一张表,直接保存,如果涉及多个操作,最后统一SaveChange也就实现了事务统一。

    3、EF中实体序列化去除 EntityKey字段

          如果直接把EF模型数据表对应的模型进行序列化,会得到很多跟EF相关的属性,要去掉这些多余的属性,就响应对序列化进行一些修改了。

    这里使用的是Newtonsoft.Net进行序列化的。具体封装源码:

     1     public class JsonNet
     2     {
     3         /// <summary>
     4         /// 将实体对象转换成Json字符串 
     5         /// </summary>
     6         /// <param name="item"></param>
     7         /// <returns></returns>
     8         public static string SerializeToString(object item)
     9         {
    10            return JsonConvert.SerializeObject(item, Formatting.Indented,
    11                 new JsonSerializerSettings
    12                 {
    13                     ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    14                     ContractResolver = new ExcludePropertiesContractResolver(new List<string> { "EntityKey" }),
    15                 });
    16 
    17         }
    18 
    19         /// <summary>
    20         /// 将Json字符串转换成实体对象
    21         /// </summary>
    22         /// <typeparam name="T"></typeparam>
    23         /// <param name="jsonString"></param>
    24         /// <returns></returns>
    25         public static T DeserializeToEntity<T>(string jsonString)
    26         {
    27             return JsonConvert.DeserializeObject<T>(jsonString);
    28         }
    29     }
    30 
    31     public class ExcludePropertiesContractResolver : DefaultContractResolver
    32     {
    33         IEnumerable<string> lstExclude;
    34 
    35         public ExcludePropertiesContractResolver(IEnumerable<string> excludedProperties)
    36         {
    37             lstExclude = excludedProperties;
    38         }
    39 
    40         protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    41         {
    42             return base.CreateProperties(type, memberSerialization).ToList().FindAll(p => !lstExclude.Contains(p.PropertyName));
    43         }
    44     }
    View Code
  • 相关阅读:
    前端html--position,旋转变换
    前端html--背景,文本,过渡效果属性
    前端html--margin,border,padding,盒模型
    前端html--css样式选择器
    前端html--超链接,表格,表单属性
    jQuery 中的事件绑定
    JavaScript简单了解
    private,protected,public和default的区别
    html基础和CSS选择器
    JSP小结
  • 原文地址:https://www.cnblogs.com/dedeyi/p/3383919.html
Copyright © 2020-2023  润新知