Rafy 框架又添新成员:幽灵插件。本文将解释该插件的场景、使用方法、原理。

 

场景


在开发各类数据库应用系统时,往往需要在删除数据时不是真正地删除数据,而只是把数据标识为‘已删除’状态。这些数据在业务逻辑上是已经完全删除、不可用的数据,但是不能在数据库中真正的把它们删除,而是需要永久保留这些历史数据。即开发人员常说的‘假删除’功能。

这种需求往往是系统级的。往往不是针对某一张表,而很可能是针对系统中的所有表都需要实现‘假删除’功能。

 

使用方法


由于这种需求比较常见,所以我们决定专门为该功能写一个独立的 Rafy 插件。这样,开发人员需要实现假删除功能时,只需要引用该插件后,系统中所有删除的实体都自动变为‘幽灵’,同时这些幽灵数据在仓库的所有查询中都将被自动过滤。

使用步骤:

  1. 通过 Nuget Package Manager 搜索并安装 Rafy.Domain.EntityPhantom 插件。
  2. 在 DomainApp 中添加该插件:
    class JXCApp : DomainApp
    {
    protected override void InitEnvironment()
    {
    //添加幽灵插件到 Rafy 应用程序集中。
    RafyEnvironment.DomainPlugins.Add(new Rafy.Domain.EntityPhantom.EntityPhantomPlugin());
    RafyEnvironment.DomainPlugins.Add(new JXCPlugin()); base.InitEnvironment();
    }
    }

    .csharpcode {
    font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
    }
    .csharpcode pre {
    font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
    }
    .csharpcode pre {
    margin: 0em
    }
    .csharpcode .rem {
    color: #008000
    }
    .csharpcode .kwrd {
    color: #0000ff
    }
    .csharpcode .str {
    color: #006080
    }
    .csharpcode .op {
    color: #0000c0
    }
    .csharpcode .preproc {
    color: #cc6633
    }
    .csharpcode .asp {
    background-color: #ffff00
    }
    .csharpcode .html {
    color: #800000
    }
    .csharpcode .attr {
    color: #ff0000
    }
    .csharpcode .alt {
    width: 100%; margin: 0em; background-color: #f4f4f4
    }
    .csharpcode .lnum {
    color: #606060
    }

  3. 为需要幽灵功能的实体打开该功能,需要在实体元数据配置中进行配置:

    internal class UserConfig : JXCEntityConfig<User>
    {
    protected override void ConfigMeta()
    {
    Meta.MapTable().MapAllProperties(); //在实体配置中加入此行代码,为实体启用幽灵功能。
    Meta.EnablePhantoms();
    }
    }

    .csharpcode {
    font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
    }
    .csharpcode pre {
    font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
    }
    .csharpcode pre {
    margin: 0em
    }
    .csharpcode .rem {
    color: #008000
    }
    .csharpcode .kwrd {
    color: #0000ff
    }
    .csharpcode .str {
    color: #006080
    }
    .csharpcode .op {
    color: #0000c0
    }
    .csharpcode .preproc {
    color: #cc6633
    }
    .csharpcode .asp {
    background-color: #ffff00
    }
    .csharpcode .html {
    color: #800000
    }
    .csharpcode .attr {
    color: #ff0000
    }
    .csharpcode .alt {
    width: 100%; margin: 0em; background-color: #f4f4f4
    }
    .csharpcode .lnum {
    color: #606060
    }

 

效果


所有继承自 Entity 的实体都会统一的添加一个 IsPhantom 的属性。这个属性表示这个实体是否为‘幽灵’,即已经删除的数据。

  • 开发者可以使用 Meta.EnablePhantoms() 来为某个指定的实体类型开启‘幽灵’功能。
  • 开启该功能的实体的 IsPhantom 属性会自动映射到数据库中。
  • 在保存实体时,如果要删除一个聚合实体,则这个聚合中的所有实体都将会被标记为‘幽灵’状态。
  • 在查询实体时,所有的查询,都将会自动过滤掉所有‘幽灵’状态的数据。(手写 SQL 查询的场景不在考虑范围内。)
  • 使用批量导入数据插件进行数据的批量导入时,批量删除的实体同样都会被标记为‘幽灵’状态。

运行程序后,数据库中的字段,已经自动添加上 IsPhantom 字段了:

在使用 GetAll 查询所有实体时,框架自动加上一 IsPhantom = false 的过滤条件:

SELECT *
FROM [User]
WHERE [User].[IsPhantom] = @p0
ORDER BY [User].[Id] ASC
Parameters:False

.csharpcode {
font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
}
.csharpcode pre {
font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
}
.csharpcode pre {
margin: 0em
}
.csharpcode .rem {
color: #008000
}
.csharpcode .kwrd {
color: #0000ff
}
.csharpcode .str {
color: #006080
}
.csharpcode .op {
color: #0000c0
}
.csharpcode .preproc {
color: #cc6633
}
.csharpcode .asp {
background-color: #ffff00
}
.csharpcode .html {
color: #800000
}
.csharpcode .attr {
color: #ff0000
}
.csharpcode .alt {
width: 100%; margin: 0em; background-color: #f4f4f4
}
.csharpcode .lnum {
color: #606060
}数据的删除,变为更新表中对应行的 IsPhantom 字段为 True:

UPDATE [User] SET [Name] = @p0,[IsPhantom] = @p1 WHERE [Id] = @p2
Parameters:"Name",True,3

.csharpcode {
font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
}
.csharpcode pre {
font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
}
.csharpcode pre {
margin: 0em
}
.csharpcode .rem {
color: #008000
}
.csharpcode .kwrd {
color: #0000ff
}
.csharpcode .str {
color: #006080
}
.csharpcode .op {
color: #0000c0
}
.csharpcode .preproc {
color: #cc6633
}
.csharpcode .asp {
background-color: #ffff00
}
.csharpcode .html {
color: #800000
}
.csharpcode .attr {
color: #ff0000
}
.csharpcode .alt {
width: 100%; margin: 0em; background-color: #f4f4f4
}
.csharpcode .lnum {
color: #606060
}

 

原理


幽灵插件的原理比较简单。在 Rafy 框架的基础上,以插件的形式对 Rafy 框架中实体的数据层进行了扩展。在启用实体的幽灵功能后,该实体的 DataProvider 类型的 Deleting、Querying 事件都会被监听并扩展:

/// <summary>
/// 数据的删除、查询的拦截器。
/// </summary>
internal static class PhantomDataInterceptor
{
internal static void Intercept()
{
RepositoryDataProvider.Deleting += RepositoryDataProvider_Deleting;
RepositoryDataProvider.Querying += RepositoryDataProvider_Querying;
}
}

.csharpcode {
font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
}
.csharpcode pre {
font-size: small; font-family: consolas, "Courier New", courier, monospace; color: black; background-color: #ffffff
}
.csharpcode pre {
margin: 0em
}
.csharpcode .rem {
color: #008000
}
.csharpcode .kwrd {
color: #0000ff
}
.csharpcode .str {
color: #006080
}
.csharpcode .op {
color: #0000c0
}
.csharpcode .preproc {
color: #cc6633
}
.csharpcode .asp {
background-color: #ffff00
}
.csharpcode .html {
color: #800000
}
.csharpcode .attr {
color: #ff0000
}
.csharpcode .alt {
width: 100%; margin: 0em; background-color: #f4f4f4
}
.csharpcode .lnum {
color: #606060
}

在查询时,框架自动分析出当前查询的 SQL 树,并在主查询上加上 IsPhantom = false 的过滤条件。

有兴趣的同学,可以查看 Rafy 框架源码。

 

PS:该文已经纳入《 Rafy 用户手册》中。

Rafy 框架 - 幽灵插件(假删除)的更多相关文章

  1. Rafy 框架 - 流水号插件

    Rafy 框架又添新成员:流水号插件.本文将解释 Rafy 框架中的流水插件的场景.使用方法. 场景 在开发各类数据库应用系统时,往往需要生成从一开始的流水号,有时还需要按月或者按日进行独立生成,如下 ...

  2. Rafy 框架 - 时间戳插件

    本文将解释 Rafy 框架中的时间戳插件的场景.使用方法.原理. 场景 在开发各类数据库应用系统时,业务领域实体往往需要包含"创建时间"."最后更新时间".&q ...

  3. Rafy框架

    l  什么是Rafy框架? -------- Rafy 是一个面向企业级开发的插件化快速开发框架. l  Rafy的优点是什么? ------快速开发.产品线工程.一套代码可同时生成并运行 C/S.单 ...

  4. Rafy 框架 - 使用 SqlTree 查询

    本文介绍如何使用 Rafy 框架中的 Sql Tree 查询: 除了开发者常用的 Linq 查询,Rafy 框架还提供了 Sql 语法树的方式来进行查询. 这种查询方式下,开发者不需要直接编写真正的 ...

  5. 使用 NuGet 下载最新的 Rafy 框架及文档

    为了让开发者更方便地使用 Rafy 领域实体框架,本月,我们已经把最新版本的 Rafy 框架程序集发布到了 nuget.org 上,同时,还把 RafySDK 的最新版本发布到了 VisualStud ...

  6. 一位同事对 Rafy 框架的一些建议及我的回复

    下面是一位同事对当前的产品开发框架提出的一些建议,以及我的回复.我觉得一些问题提得有一定的代表性,在征得本人同意后,将本邮件发布在博客中. 同时,也非常希望对框架.产品有好的建议的小伙伴,都可以给我发 ...

  7. Rafy 框架:领域控制器

    本文简要说明如何使用 Rafy 框架中的领域控制器. 简介 领域控制器是 Rafy 框架中用于封装领域逻辑的主要方式. 在控制器中,开发者可以封装大量的业务逻辑,并向外暴露业务接口.内部的逻辑在实现时 ...

  8. Rafy 框架 - 通用查询条件(CommonQueryCriteria)

    在应用开发过程中,有 80% 的场景下,开发者所需要的实体查询,查询条件中其实都是一些简单的属性匹配,又或是一些属性匹配的简单组合.Rafy 为这样的场景提供了更为方便使用的 API:CommonQu ...

  9. 快速开发~Rafy框架的初步认识

    当我们开始使用EF的同时,是不是就会更好的认识了其他的ORM框架,最近接触了Rafy的使用,感觉还是蛮有兴趣去学习的,虽然最初的我到现在看的并不深入,但是我个人感觉还是可以简单地做一些总结的啦,或许语 ...

随机推荐

  1. Ajax使用WCF实现小票pos机打印源码

    通过ajax跨域方式调用WCF服务,实现小票pos机的打印,源码提供web方式,客户端方式测试,服务驻留右侧底部任务栏,可控制服务开启暂停,用户可自定义小票打印模板,配合零售录入. qq  22945 ...

  2. MSSQL 事务,视图,索引,存储过程,触发器

    事务 事务是一种机制.是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行. 在数据库系统上执行并发操作时事务是作为最小的控制单元来使用的.这特别适用于多用户同时操作的数据 ...

  3. 在VMware上安装CentOS -7

    1.下载好VMware 2.准备好CentOS的镜像文件 3.打开VMware创建新的虚拟机 选择自定义高级后按下一步 继续下一步 选择稍后安装操作系统 客户机操作系统选择Linux,版本选择Cent ...

  4. centos6.5 nginx-1.8.0和ftp搭建图片服务器

    一.Nginx的安装步骤 1.Nginx安装环境: gcc: 安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gcc:yum install gcc-c+ ...

  5. Linux命令

    系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...

  6. Create a bridge using a tagged vlan (8021.q) interface

    SOLUTION VERIFIED April 27 2013 KB26727 Environment Red Hat Enterprise Linux 5 Red Hat Enterprise Li ...

  7. [转]thinkphp 模板显示display和assign的用法

    thinkphp 模板显示display和assign的用法 $this->assign('name',$value); //在 Action 类里面使用 assign 方法对模板变量赋值,无论 ...

  8. WiFi QC 自动测试:ixChariot API初探

    Chariot虽然给我们提供了友好的界面,但是必须使用命令行或者使用它的API才能 实现自动测试.Chariot在安装的时候会让你选择命令行界面组件,在它的安装目录下面有一些工具, 暂时还不知道是干什 ...

  9. Linux.NET实战手记—自己动手改泥鳅(下)

    在上回合中,我们不痛不痒的把小泥鳅的数据库从只能供在Windows下运行的Access数据库改为支持跨平台的MYSQL数据库,毫无营养的修改,本回合中,我们将把我们修改后得来的项目往Linux中部署. ...

  10. 兼容Mono的下一代云环境Web开发框架ASP.NET vNext

    微软在2014年5月12日的TechEd大会上宣布将会发布下一代ASP.NET框架ASP.NET vNext的预览.此次发布的ASP.NET框架与以前相比发生了根本性的变化,凸显了微软“云优先”(cl ...