回到目录

关于逻辑删除

对于逻辑删除之前的做法是在实体类中加个字段,一般是status,其中一种状态是删除,当然也有其它做法,如加个bool的字段IsDeleted,这些其实都过于武断,即它在基类里加上后,所以实体类都会有这种特性,而对于现实的数据表,可能不显示这种逻辑删除的特性,如关系表,日志表,可能删除就是物理上的直接delete,而这种删除字段加上去,我们的做也是在业务层手动调用update方法,或者在底层提供一个delete方法的重载,总之,感觉不是很爽!

看了ABP的软删除之后,对大叔有了新的启发,即提出一个逻辑删除的接口,所以需要这个字段的实体都去实现这个接口即可!

逻辑删除的接口(对实体属性的装饰)

   /// <summary>
/// 具有逻辑删除的接口,实体需要实现这个接口,将IsDeleted实现
/// 在仓储实现类中,delete方法判断实体是否实现了ILogicDeleteBehavor这个接口,然后再决定是否逻辑删除
/// </summary>
public interface ILogicDeleteBehavor
{
/// <summary>
/// 是否已经删除,默认为false
/// </summary>
bool IsDeleted { get; set; }
}

这个接口很干净,只有一个属性,这个属性用来标识删除的状态,true表示已经删除,在进行select操作时我们需要将这个状态过滤,在delete方法里,我们也可以通过判断当前实体是否属于ILogicDeleteBehavor接口而对它采取是否进行逻辑删除!

实体多继承一个接口,完成某个特定的功能

 public partial class WebManageUsers :
Lind.DDD.Domain.Entity,
ILogicDeleteBehavor,
IStatusBehavor
{
#region IStatusBehavor 成员 public Status DataStatus { get; set; } #endregion #region ILogicDeleteBehavor 成员 public bool IsDeleted { get; set; } #endregion
public WebManageUsers()
{
this.WebManageRoles = new HashSet<WebManageRoles>();
this.WebDepartments = new HashSet<WebDepartments>();
}
[DisplayName("登陆名"), Required]
public string LoginName { get; set; }
[DisplayName("密码"), Required]
public string Password { get; set; }
[DisplayName("真实姓名"), Required]
public string RealName { get; set; }
[DisplayName("手机")]
public string Mobile { get; set; }
[DisplayName("电子邮件")]
public string Email { get; set; }
[DisplayName("描述")]
public string Description { get; set; }
[DisplayName("操作者")]
public string Operator { get; set; }
[DisplayName("所属项目")]
public Nullable<int> WebSystemID { get; set; }
public virtual ICollection<WebManageRoles> WebManageRoles { get; set; }
public virtual ICollection<WebDepartments> WebDepartments { get; set; } }

本例采用的是EF的CodeFirst方式,所以需要将自己定义实体,然后根据实体自动生成数据库.

删除方法直接判断实体是否实现了某个接口

 public void Delete(TEntity item)
{
if (item != null)
{
if (item is ILogicDeleteBehavor)
{
//逻辑删除
var pkList = GetPrimaryKey().Select(i => i.Name);
var entityType = typeof(TEntity);
List<object> primaryArr = new List<object>();
foreach (var primaryField in pkList)
{
primaryArr.Add(entityType.GetProperty(primaryField).GetValue(item, null));
}
var old = this.Find(primaryArr.ToArray());
(old as ILogicDeleteBehavor).IsDeleted = true;
this.Update(old);
}
else
{
//物理删除
Db.Set<TEntity>().Attach(item as TEntity);
Db.Entry(item).State = EntityState.Deleted;
Db.Set<TEntity>().Remove(item as TEntity);
this.SaveChanges();
} }
}

上面的设置,对于在列表里删除某个对象已经可以实现了,而如何去过滤列表里的记录呢,当然直接在DbSet<TEntity>()里去过滤是最好的,但没有直接的方式,因为我们的IsDeleted属性没有对外暴露,而对于Linq to Entity来说,你无法在查询表达式中输

入EDM之外的元素名(那也不认,它只认实体类型),还好在ABP里我找到了不错的方法,就是在数据上下文的OnModelCreating方法上,添加过滤器,这个过滤器需要我们安装EntityFramework.DynamicFilters包,直接用Nuget可以安装.

ModelBuilder.Filter完成对集合的全局过滤

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Filter("LogicDelete", (Lind.DDD.Domain.ILogicDeleteBehavor d) => d.IsDeleted, false);
}

这样在所有Linq Select语句之前都会添加d.IsDeleted==false这个参数完成逻辑删除的过滤功能!

是不是很爽,很酷!

对于实体中其它的比较有特点的属性,而又不是全局的属性,我们都可以使用接口的方式进行定义,这类似于装饰模式,即将某个属性装饰成某个接口,而在程序的另一端直接去操作这个接口即可

回到目录

Lind.DDD.ILogicDeleteBehavor~逻辑删除的实现的更多相关文章

  1. Lind.DDD敏捷领域驱动框架~介绍

    回到占占推荐博客索引 最近觉得自己的框架过于复杂,在实现开发使用中有些不爽,自己的朋友们也经常和我说,框架太麻烦了,要引用的类库太多:之前架构之所以这样设计,完全出于对职责分离和代码附复用的考虑,主要 ...

  2. Lind.DDD.Caching分布式数据集缓存介绍

    回到目录 戏说当年 大叔原创的分布式数据集缓存在之前的企业级框架里介绍过,大家可以关注<我心中的核心组件(可插拔的AOP)~第二回 缓存拦截器>,而今天主要对Lind.DDD.Cachin ...

  3. Lind.DDD.API核心技术分享

    回到目录 关于Lind.DDD框架里API框架的技术点说明 讲解:张占岭 花名:仓储大叔 主要框架:Lind.DDD 目录 关于Lind.DDD.Authorization 关于授权的原理 关于Api ...

  4. Lind.DDD.LindAspects方法拦截的介绍

    回到目录 什么是LindAspects 之前写了关于Aspects的文章<Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP>,今天主要在设计思想上进 ...

  5. Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP

    回到目录 .Net MVC之所以发展的如些之好,一个很重要原因就是它公开了一组AOP的过滤器,即使用这些过滤器可以方便的拦截controller里的action,并注入我们自己的代码逻辑,向全局的异常 ...

  6. Lind.DDD.Repositories.Mongo层介绍

    回到目录 之前已经发生了 大叔之前讲过被仓储化了的Mongodb,而在大叔开发了Lind.DDD之后,决定把这个东西再搬到本框架的仓储层来,这也是大势所趋的,毕竟mongodb是最像关系数据库的NoS ...

  7. Lind.DDD.Repositories.Redis层介绍

    回到目录 之前已经发生了 大叔之前介绍过关于redis的文章,有缓存,队列,分布式pub/sub,数据集缓存以及仓储redis的实现等等,而今天在Lind.DDD的持久化组件里,redis当然也有一席 ...

  8. Lind.DDD.Events领域事件介绍

    回到目录 闲话多说 领域事件大叔感觉是最不好讲的一篇文章,所以拖欠了很久,但最终还是在2015年年前(阴历)把这个知识点讲一下,事件这个东西早在C#1.0时代就有了,那时学起来也是一个费劲,什么是委托 ...

  9. Lind.DDD.Authorization用户授权介绍

    回到目录 Lind.DDD.Authorization是Lind.DDD框架的组成部分,之所以把它封装到框架里,原因就是它的通用性,几乎在任何一个系统中,都少不了用户授权功能,用户授权对于任何一个系统 ...

随机推荐

  1. 《Entity Framework 6 Recipes》中文翻译系列 (19) -----第三章 查询之使用位操作和多属性连接(join)

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 3-16  过滤中使用位操作 问题 你想在查询的过滤条件中使用位操作. 解决方案 假 ...

  2. Hystrix框架1--入门

    介绍 在开发应用中或多或少会依赖各种外界的服务,利用各个服务来完成自己的业务需求,现在流行的微服务架构更是离不开各个服务之间的调用,这就导致整体应用的可用性依赖于各个依赖服务的可用性. 比如一个依赖3 ...

  3. fc-san

    在SAN网络中,所有的数据传输在高速.高带宽的网络中进行,SAN存储实现的是直接对物理硬件的块级存储访问,提高了存储的性能和升级能力. 早期的SAN采用的是光纤通道(FC,Fibre Channel) ...

  4. Android开发-之第一个程序:HelloWorld!

    小编觉得不管学习什么编程的时候,第一个程序都是要求打印输出一个"HelloWorld!",那就从最简单的HelloWorld开始吧!哈哈~~~~ 一.创建一个Android工程 1 ...

  5. MongoDB 维护Replica Set

    在每个MongoDB(版本 3.2.9) Instance中,都有一个本地数据库(local),用于存储 Replication 进程的信息和本地数据.local 数据库的特性是:位于local数据库 ...

  6. ASP.NET MVC之分部视图和ChildAction(三)

    前言 上节我们已经非常清晰并且明确的讲了@Html.ActionLink的作用,这一节我们开始讲讲分部视图以及孩子Action. 话题 在C#中我们知道继承的目的是为了代码的复用,在Web应用程序同样 ...

  7. angular开发者吐槽react+redux的复杂:“一个demo证明你的开发效率低下”

    曾经看到一篇文章,写的是jquery开发者吐槽angular的复杂.作为一个angular开发者,我来吐槽一下react+redux的复杂. 例子 为了让大家看得舒服,我用最简单的一个demo来展示r ...

  8. H5基于iScroll实现下拉刷新,上拉加载更多

    前言 前一段有个手机端的项目需要用到下拉刷新和上拉加载更多的效果,脑海里第一反映就是微博那种效果,刚开始的理解有些偏差,以为下拉也是追加数据,上拉也是追加数据,后请教同事后发现其实下拉只是刷新最新数据 ...

  9. CSS实现单行与多行文字省略(truncation)

    在上一篇文章小div布局之卡片堆叠(card-stacking)中有多行文字溢出省略的效果,这篇文章就对这种效果(包括单行文字溢出省略)的实现做个简单的记录,以防自己忘记.具体来说,就是要实现这种文字 ...

  10. ThinkPHP中的快捷函数小结

    U() 制作url地址的快捷函数 C(名称) 获得配置变量(convertion.php config.php)信息C(名称,值) 设置配置变量信息 L() 获得语言变量信息E() 给页面输出错误信息 ...