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

主要解决的问题有:

1、EF上下文管理

2、BaseRepository的封装

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

1、EF上下文管理

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

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

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

    public class DbContextFactory
{
private static string efKey = "ef_key"; public static RBACEntities GetContext()
{
RBACEntities db = CallContext.GetData(efKey) as RBACEntities;
if (db == null)
{
db = new RBACEntities();
CallContext.SetData(efKey,db);
}
Debug.WriteLine("EF上下文获取:" + db.GetHashCode() + ",时间:" + DateTime.Now.ToString("hh-mm-ss ffff"));
return db;
} public static void Dispose()
{
var context=GetContext();
Debug.WriteLine("EF上下文释放:" + context.GetHashCode() + ",时间:" + DateTime.Now.ToString("hh-mm-ss ffff"));
context.Dispose();
}
}

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

        protected void Application_EndRequest()
{
Dedeyi.RBAC2.Core.Model.DbContextFactory.Dispose();
}

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

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

2、BaseRepository的封装

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

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

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

  public class BaseRepository<TEntity> where TEntity: EntityObject
{
protected RBACEntities RBACContext { get; set; }
protected ObjectSet<TEntity> DbSet { get; set; } protected virtual IQueryable<TEntity> Entities
{
get { return RBACContext.CreateObjectSet<TEntity>(); }
} public BaseRepository()
{
this.RBACContext = DbContextFactory.GetContext();
this.DbSet=RBACContext.CreateObjectSet<TEntity>();
} public IQueryable<TEntity> GetPage<TKey>(int pageIndex, int pageSize,Expression<Func<TEntity,TKey>> orderBy, out int totalRecord)
{
totalRecord = DbSet.Count();
return this.DbSet
.OrderByDescending(orderBy)
.Skip((pageIndex - ) * pageSize)
.Take(pageSize)
.AsQueryable();
} public IQueryable<TEntity> GetPage<TKey>(int pageIndex, int pageSize, Expression<Func<TEntity, TKey>> orderBy, Expression<Func<TEntity, bool>> where, out int totalRecord)
{
var res=DbSet.Where(where); totalRecord = res.Count();
return res
.OrderByDescending(orderBy)
.Skip((pageIndex - ) * pageSize)
.Take(pageSize)
.AsQueryable();
} public TEntity Add(TEntity entity,bool saveChange)
{
RBACContext.CreateObjectSet<TEntity>().AddObject(entity);
if (saveChange)
{
RBACContext.SaveChanges();
}
return entity;
} public TEntity Edit(TEntity entity, bool saveChange)
{
RBACContext.CreateObjectSet<TEntity>().Attach(entity);
RBACContext.ObjectStateManager.ChangeObjectState(entity,System.Data.EntityState.Modified);
if (saveChange)
{
RBACContext.SaveChanges();
}
return entity;
} public void Delete(TEntity entity, bool saveChange)
{
RBACContext.CreateObjectSet<TEntity>().DeleteObject(entity);
if (saveChange) { RBACContext.SaveChanges(); }
}
}

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

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

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

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

     public class JsonNet
{
/// <summary>
/// 将实体对象转换成Json字符串
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public static string SerializeToString(object item)
{
return JsonConvert.SerializeObject(item, Formatting.Indented,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = new ExcludePropertiesContractResolver(new List<string> { "EntityKey" }),
}); } /// <summary>
/// 将Json字符串转换成实体对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="jsonString"></param>
/// <returns></returns>
public static T DeserializeToEntity<T>(string jsonString)
{
return JsonConvert.DeserializeObject<T>(jsonString);
}
} public class ExcludePropertiesContractResolver : DefaultContractResolver
{
IEnumerable<string> lstExclude; public ExcludePropertiesContractResolver(IEnumerable<string> excludedProperties)
{
lstExclude = excludedProperties;
} protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return base.CreateProperties(type, memberSerialization).ToList().FindAll(p => !lstExclude.Contains(p.PropertyName));
}
}

DB First 中对Repository 层封装的几点小记的更多相关文章

  1. 使用DapperSimpleCRUD对Repository层进行封装

    通过前面的两篇文章使用Dapper操作Mysql数据库与使用Dapper进行参数化查询,大致介绍了Dapper的一些基本操作和简单使用,在实际的使用当中,我们可以把项目简单的分为MVC+Service ...

  2. 【redis】5.spring boot项目中,直接在spring data jpa的Repository层使用redis +redis注解@Cacheable直接在Repository层使用,报错问题处理Null key returned for cache operation

    spring boot整合redis:http://www.cnblogs.com/sxdcgaq8080/p/8028970.html 首先,明确一下问题的场景 之前在spring boot整合re ...

  3. MVC架构中的Repository模式 个人理解

    关于MVC架构中的Repository模式   个人理解:Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间.它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接 ...

  4. PHP MVC 中的MODEL层

    Model层,就是MVC模式中的数据处理层,用来进行数据和商业逻辑的装封 三.实现你的Mode层 Model层,就是MVC模式中的数据处理层,用来进行数据和商业逻辑的装封,进行他的设计的时候设计到三个 ...

  5. SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装

    SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装 >>>>>>>& ...

  6. 小程序api请求层封装(Loading全局配置)

    前言 小程序开发,没有vue中的axios那么好使,请求层的封装需要自己来搞. 当然请求层的配置少不了loading,这里索性也就将loading做一个配置,避免以后重复造轮子 请求封装 小程序中有封 ...

  7. Altium 中异形焊盘异形封装的创建图文教程

    Altium 中异形焊盘异形封装的创建图文教程 一般不规则的焊盘被称为异型焊盘,典型的有金手指.大型的器件焊盘或者板子上需要添加特殊形状的铜箔(可以制作一个特殊封装代替). 如图27所示,此处我们以一 ...

  8. MVC中Model BLL层Model模型互转

    MVC中Model BLL层Model模型互转 一. 模型通常可以做2种:充血模型和失血模型,一般做法是模型就是模型,不具备方法来操作,只具有属性,这种叫做失血模型(可能不准确):具备对模型一定的简单 ...

  9. Laravel 中使用 Repository 模式

    在本文中,我会向你展示如何在 Laravel 中从头开始实现 repository 设计模式.我将使用 Laravel 5.8.3 版,但 Laravel 版本不是最重要的.在开始写代码之前,你需要了 ...

随机推荐

  1. javaWeb中,文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  2. Codeforces 938.C Constructing Tests

    C. Constructing Tests time limit per test 1 second memory limit per test 256 megabytes input standar ...

  3. jquery动态添加的元素绑定的事件不生效的问题

    我们可以通过 $(document).on('click', '#xxx', callback) 这种形式解决. 原因,一般情况下,我们是通过 $('#xxx').click(callback) 这种 ...

  4. git untrack file

    git update-index should do what you want This will tell git you want to start ignoring the changes t ...

  5. 我是大SB

    哈哈哈 我就是个大SB!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  6. 学大伟业 2017 国庆 Day1

    期望得分:100+100+20=220 实际得分:100+100+20=220 (好久没有期望==实际了 ,~\(≧▽≦)/~) 对于 a........a 如果 第1个a 后面出现的第1个b~z 是 ...

  7. 【BZOJ】1706: [usaco2007 Nov]relays 奶牛接力跑

    [题意]给定m条边的无向图,起点s,终点t,要求找出s到t恰好经过n条边的最短路径.n<=10^6,m<=100. [算法]floyd+矩阵快速幂 [题解] 先对点离散化,得到点数N. 对 ...

  8. 《Troubleshooting SQL Server》读书笔记-CPU使用率过高(上)

    第三章 High CPU Utilization. CPU使用率过高问题很容易被发现,但是诊断却不是很容易.CPU使用过高很多时候会成为其它问题的替罪羊,所以在确认和故障诊断时要抽丝剥茧. 调查CPU ...

  9. 【洛谷 P4219】 [BJOI2014]大融合(LCT)

    题目链接 维护子树信息向来不是\(LCT\)所擅长的,所以我没搞懂qwq 权当背背模板吧.Flash巨佬的blog里面写了虽然我没看懂. #include <cstdio> #define ...

  10. 【leetcode 简单】第二十七题 二叉树的最小深度

    给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,null,15,7], ...