DB First 中对Repository 层封装的几点小记
在数据库表创建完成的情况下,使用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 层封装的几点小记的更多相关文章
- 使用DapperSimpleCRUD对Repository层进行封装
通过前面的两篇文章使用Dapper操作Mysql数据库与使用Dapper进行参数化查询,大致介绍了Dapper的一些基本操作和简单使用,在实际的使用当中,我们可以把项目简单的分为MVC+Service ...
- 【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 ...
- MVC架构中的Repository模式 个人理解
关于MVC架构中的Repository模式 个人理解:Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间.它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接 ...
- PHP MVC 中的MODEL层
Model层,就是MVC模式中的数据处理层,用来进行数据和商业逻辑的装封 三.实现你的Mode层 Model层,就是MVC模式中的数据处理层,用来进行数据和商业逻辑的装封,进行他的设计的时候设计到三个 ...
- SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装
SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装 >>>>>>>& ...
- 小程序api请求层封装(Loading全局配置)
前言 小程序开发,没有vue中的axios那么好使,请求层的封装需要自己来搞. 当然请求层的配置少不了loading,这里索性也就将loading做一个配置,避免以后重复造轮子 请求封装 小程序中有封 ...
- Altium 中异形焊盘异形封装的创建图文教程
Altium 中异形焊盘异形封装的创建图文教程 一般不规则的焊盘被称为异型焊盘,典型的有金手指.大型的器件焊盘或者板子上需要添加特殊形状的铜箔(可以制作一个特殊封装代替). 如图27所示,此处我们以一 ...
- MVC中Model BLL层Model模型互转
MVC中Model BLL层Model模型互转 一. 模型通常可以做2种:充血模型和失血模型,一般做法是模型就是模型,不具备方法来操作,只具有属性,这种叫做失血模型(可能不准确):具备对模型一定的简单 ...
- Laravel 中使用 Repository 模式
在本文中,我会向你展示如何在 Laravel 中从头开始实现 repository 设计模式.我将使用 Laravel 5.8.3 版,但 Laravel 版本不是最重要的.在开始写代码之前,你需要了 ...
随机推荐
- hdu6166 Senior Pan
Senior Pan Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Tot ...
- Qt ------ 我定义的规则 之 对象命名规则
类型 + 特性,比如 button_closeLigth 非公有的变量前面要加上小写m_ (指的修饰符为private时) 静态变量前面加上小写s_ 其它变量以小写字母开头 静态变量全大写 (sta ...
- 进程间共享数据Manager
一.前言 进程间的通信Queue()和Pipe(),可以实现进程间的数据传递.但是要使python进程间共享数据,我们就要使用multiprocessing.Manager. Manager()返回的 ...
- Mac(Linux)上安装memcached步骤
Mac上安装memcached类似于在Linux平台上安装memcached. 主要需要做两块: 一.安装libevent库: 二.安装memcached; 一.安装libevent库 libeven ...
- CF760 D Travel Card 简单DP
link 题意:乘车,有3种票 1.20块坐1站 2.坐90分钟,50块 3.坐1440分钟,120块 现给出到达每个站的时间,问最优策略 思路: 简单DP,限定条件的3个转移方向,取最小的那个就行了 ...
- elasticsearch ik中文分词器的安装配置使用
安装步骤 https://github.com/medcl/elasticsearch-analysis-ik 以插件形式安装: [elsearch@localhost elasticsearch- ...
- codeblocks快捷键(转)
==日常编辑== • 按住Ctrl滚滚轮,代码的字体会随你心意变大变小.• 在编辑区按住右键可拖动代码,省去拉(尤其是横向)滚动条之麻烦:相关设置:Mouse Drag Scrolling.• Ctr ...
- 自己封装的ASP.NET的MYSQL的数据库操作类
/** * 作者:牛腩 * 创建时间:2010年3月7日17时35分 * 类说明:对MYSQL数据库的操作类 */ using System; using System.Data; using MyS ...
- 在eclipse安装mybatis的插件
1.在help中打开 2.搜索mybatipse 3:功能简介 1:要查找某一个方法 在dao接口中某一个方法中 按住 Ctrl键 鼠标指到方法名称上 选择open xml 就会自动跳转 ...
- [NOIP2003]栈 题解(卡特兰数)
[NOIP2003]栈 Description 宁宁考虑的是这样一个问题:一个操作数序列,从1,2,一直到n(图示为1到3的情况),栈A的深度大于n. 现在可以进行两种操作: 1.将一个数,从操作数序 ...