实体框架的审计跟踪

2024-04-25

我在每个表中都有审计跟踪字段(InsertedBy、InsertedDate、UpdatedBy 和 UpdatedDate),我构建解决方案以通过覆盖 savechange() 来减少冗余:

public override int SaveChanges()
{
    foreach (var entry in ChangeTracker.Entries().Where(e =>
        e.State == System.Data.Entity.EntityState.Added || e.State == System.Data.Entity.EntityState.Modified))
    {
        Auditing.ApplyAudit(entry, User);
    }
    return base.SaveChanges();
}

public class Auditing
{
    public static void ApplyAudit(DbEntityEntry entityEntry, int User)
    {
        Type type = entityEntry.Entity.GetType();
        if (entityEntry.State.ToString() == "Added")
        {
            if (type.GetProperty("InsertedBy") != null)
            {
                entityEntry.Property("InsertedBy").CurrentValue = User;
            }
            if (type.GetProperty("InsertedDate") != null)
            {
                entityEntry.Property("InsertedDate").CurrentValue = DateTime.Now;
            }
        }
        else if (entityEntry.State.ToString() == "Modified")
        {
            if (type.GetProperty("InsertedBy") != null)
            {
                entityEntry.Property("InsertedBy").IsModified = false;
            }
            if (type.GetProperty("InsertedDate") != null)
            {
                entityEntry.Property("InsertedDate").IsModified = false;
            }
            if (type.GetProperty("UpdatedBy") != null)
            {
                entityEntry.Property("UpdatedBy").CurrentValue = User;
            }
            if (type.GetProperty("UpdatedDate") != null)
            {
                entityEntry.Property("UpdatedDate").CurrentValue = DateTime.Now;
            }
        }
    }
}

问题是: 在修改或添加之前是否在每个实体中使用反射会浪费内存和性能?如果是,是否有最佳实践? 这是另一个性能更好的代码片段还是也只使用反射?

public static void ApplyAudit(DbEntityEntry entityEntry, long User)
{
    if (entityEntry.State.ToString() == "Added")
    {
        entityEntry.Property("InsertedBy").CurrentValue = User;
        entityEntry.Property("InsertedDate").CurrentValue = DateTime.Now;
    }
    else if (entityEntry.State.ToString() == "Modified")
    {
        entityEntry.Property("InsertedBy").IsModified = false;
        entityEntry.Property("InsertedDate").IsModified = false;
        entityEntry.Property("UpdatedBy").CurrentValue = User;
        entityEntry.Property("UpdatedDate").CurrentValue = DateTime.Now;
    }
}

entityEntry.Property("InsertedBy") 是否使用反射?


反射很慢(慢是主观的),如果你想避免它,那么你需要删除如下代码:

Type type = entityEntry.Entity.GetType();
if (type.GetProperty("InsertedBy") != null)

即使速度不慢,上面的代码仍然是“有缺陷的”,因为程序员可能会错误地编写InsertBy代替InsertedBy。使用以下方法,可以在编译器的帮助下轻松避免这种情况。

使用接口并在所有需要审计的实体中实现它。

public interface IAuditable
{
    string InsertedBy { get; set; }
    // ... other properties
}

public class SomeEntity : IAuditable
{
    public string InsertedBy { get; set; }
}

public class Auditor<TAuditable> where TAuditable : IAuditable
{
    public void ApplyAudit(TAuditable entity, int userId)
    {
        // No reflection and you get compiler support
        if (entity.InsertedBy == null)
        {
            // whatever
        }
        else
        {
            // whatever
        }
    }
}

正如评论中提到的,您将获得编译器支持并且不再使用反射。我什至会更进一步,不通过int userId。我将带来用于计算的代码userId并把它放在这个类中。这样,类就可以自给自足,客户不需要向其提供此信息。

Usage:

var e = new SomeEntity();
var auditor = new Auditor<SomeEntity>();
auditor.ApplyAudit(e, 1); // 1 is userId, I am just hardcoding for brevity

或者根据您的上下文使用它:

public override int SaveChanges()
{
    var auditables = ChangeTracker.Entries().Where(e =>
        e.State == System.Data.Entity.EntityState.Added || e.State == System.Data.Entity.EntityState.Modified)
        .OfType<IAuditable>();
    var auditor = new Auditor<IAuditable>();
    foreach (var entry in auditables)
    {
        // 1 is userId, I am just hardcoding for brevity
        auditor.ApplyAudit(entry, 1);
    }
    return base.SaveChanges();
}

这意味着所有可审计的实体都需要实施IAuditable界面。 EF 为您的实体生成部分类,但不要修改这些部分类,因为下次运行自定义工具时,它将被清除。

相反,创建另一个同名的分部类并实现IAuditable.

public partial class SomeEntity : IAuditable {}

更好的方法是创建自定义 T4 模板,以便它使用代码创建分部类: IAuditable。请参见本文 http://matthidinger.com/archive/2010/02/09/customizing-the-entity-framework-t4-template-suppressing-code-analysis/如何做到这一点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实体框架的审计跟踪 的相关文章

  • ASP MVC4 - 通过视图模型传递列表以查看

    我有一个模型人物 其中包括出生日期等字段 我想将所有人的列表以及每个人的计算年龄传递给视图 因此 视图模型 public class vm PersonList public Person Person get set public int
  • 是否有与 SQL Server newsequentialid() 等效的 .NET

    我们使用 GUID 作为主键 您知道默认情况下它是集群的 将新行插入表中时 它将插入表中的随机页 因为 GUID 是随机的 这会对性能产生可衡量的影响 因为数据库始终会分割数据页 碎片 但我使用顺序 GUID 的主要原因是因为我希望将新行插
  • lambda 始终返回“1”

    有这样的代码 include
  • C++ 中的可变参数函数声明中省略了逗号

    我习惯于这样声明可变参数函数 int f int n 读书时C 编程语言我发现书中的声明省略了逗号 int f int n the comma has been omitted 这个语法似乎是 C 特定的 因为当我尝试使用 C 编译器编译它
  • 仅使用 1 行 C++ 初始化 2d 向量

    我需要能够初始化一个 2D 向量 int同一条线我在其中创建它 更具体地说 我必须创建一个3x2大小 2D 向量并将其所有值设置为 0 仅使用1行代码 有没有一种方法可以在不使用 for 循环和几行代码的情况下完成此操作 尝试这个 std
  • 将文件扩展名与应用程序关联

    我编写了一个编辑特定文件类型的程序 我想为用户提供在启动时将我的应用程序设置为该文件类型的默认编辑器的选项 因为我不需要安装程序 我尝试编写一个可重用的方法 通过向 HKEY CLASSES ROOT 添加一个键来为我关联一个文件 最好在任
  • 从文本文件中读取所有内容 - C

    我正在尝试从文本文件中读取所有内容 这是我写的代码 include
  • 使用工作表作为数据源的 VSTO Excel 的简单示例

    我想我遇到了 最简单的答案是最难找到的答案 的情况 而且我还没有遇到过任何搜索能够以直接的方式给我这个答案 这是为了Excel 2010 and VS 2010在现有 VSTO C 项目中 我有一个 Excel 工作表 其中包含 4 列数据
  • 如何找到 QDockWidget 标题栏的高度?

    我正在尝试找到 a 的高度QDockWidget标题栏 以便对自定义布局进行一些智能调整大小 但标题栏不是单独的小部件 它内置于停靠小部件的私有布局中 并且没有成员可以访问它 还有其他方法可以找到它的高度吗 是的 您可以使用以下命令找到标题
  • 如何为用户提供给定 boost::spirit 语法的自动完成建议?

    我正在使用 Boost Spirit 在我的 C GUI 应用程序中为非技术用户构建简单的 数据过滤器 语言 语言与纯英语非常相似 并且可以解析为 AST 我被要求使该过程尽可能对用户友好 因此我希望提供类似 CLang 的错误消息 无法识
  • 策略模式的现实示例

    我一直在读关于OCP原理 http en wikipedia org wiki Open closed principle以及如何使用策略模式来实现这一目标 我打算尝试向几个人解释这一点 但我能想到的唯一例子是根据 订单 的状态使用不同的验
  • 在javascript中调用c#函数[重复]

    这个问题在这里已经有答案了 可能的重复 从 Javascript 调用 ASP NET 函数 https stackoverflow com questions 3713 call asp net function from javascr
  • 使用 PrimarySearcher.FindAll() 时出现内存泄漏

    我也有一个使用插件和应用程序域长时间运行的服务 并且由于使用目录服务而出现内存泄漏 请注意 我正在使用 system directoryservices accountmanagement 但据我了解 它使用相同的底层 ADSI API 因
  • invoke_result获取模板成员函数的返回类型

    如何获取模板成员函数的结果类型 下面的最小示例说明了该问题 include
  • 创建 .ICS 文件,添加到 Outlook

    我正在创建一个简单的应用程序 允许用户下载 ICS 文件 并将其导入到他们选择的日历应用程序 站点中 我对创建过程感到满意 但对在 Outlook 中打开它们有疑问 将使用C ASP NET进行开发 当我打开一个日历时 它会添加一个新日历
  • ASP.NET 5 (vNext) - 配置

    我正在尝试学习 ASP NET 5 我在 Mac OS X 上使用它 此时 我有一个如下所示的 config json 文件 配置 json AppSettings Environment dev DbSettings AppConnect
  • C# - 使用 Linq 获取 Attribute 的属性

    我有一个属性 它本身就有属性 我想访问这些属性之一 布尔值 并检查它是否正确 我能够检查属性是否已设置 但这就是全部 至少对于 linq 来说是这样 属性 public class ImportParameter System Attrib
  • C++ 中的 Ofstream 数组

    我想要在我的项目中使用 41 个输出文件来在其上写入文本 首先创建一个字符串数组list为了命名这些输出文件 然后我尝试定义一个 ofstream 对象数组并使用list命名它们 但我收到此错误 outfile cannot be used
  • 如何检查多个变量是否等于同一值?

    如何比较多个项目 例如 我希望检查所有变量 A B 和 C 是否都等于字符 X 或所有三个变量都等于 O 如果其中 2 个为 X 1 个为 O 则应返回 false I tried if A B C X A B C O Do whateve
  • 如何注销多个非当前用户的会员用户?

    我正在使用属于 MVC2 默认项目一部分的 MembershipProvider 我希望能够获取用户名列表 注销用户 并在需要时销毁他们的会话 我能想到的最接近的是 foreach string userName in UserNames

随机推荐

  • 缩放 ImageView 的图像,同时将中心点保持在同一位置

    我已将预缩放位图设置为 ImageView 的源 然后我读了矩阵ImageView并通过以下方式移动 ImageView 的位图matrix postTranslate shiftX shiftY 现在我想放大 缩小图像 同时保持中心Ima
  • Android Volley POST Json 到服务器

    我正在使用 Volley 在 Android 设备和网络服务器之间传输数据 我发现有关将数据列表发送到服务器的问题 例如 我的类将生成如下数据集 1 1 aID 5 2 aID 5 3 aID 5 4 aID 5 2 1 bID 3 2 b
  • ArrayLists 比数组慢 2 倍

    我正在测试一种分子动力学算法 该算法除其他外 还有一个 Particle 类 由9 双精度数组存储粒子分量 3D 环境中的速度 力和位置 我使用 5 个输入大小测试算法 Size MB Time s 0 06 0 36 fits in ca
  • 将浏览器配置文件传递给 docker 容器内的 selenium 的正确方法是什么?

    我需要启动selenium inside docker容器 将浏览器配置文件传递给很重要webdriver Here s docker compose version 2 services worker main build app vol
  • facebook-android-sdk 错误:发布共享对话框需要publish_actions

    我需要对我的应用程序进行publish actions才能在用户墙中发布 但它被拒绝了 因为 据说 Facebook不需要publish actions 但我尝试使用共享对话框通过以下代码共享图片 SharePhoto photo new
  • Apache Spark 中的线性回归给出错误的截距和权重

    对 y 2 x1 3 x2 4 的虚拟数据集 y x1 x2 使用 MLLib LinearRegressionWithSGD 会产生错误的截距和权重 实际使用的数据是 x1 x2 y 1 0 1 6 3 2 0 2 8 6 3 0 3 1
  • 通过 Phonegap 连接到 HTTP 服务器

    我有一个服务器组件 它通过 HTTP 连接到远程服务器并获得一些响应 如果我使用 Android 版 Phonegap 我可以连接到 java 插件中的此类服务器端代码吗 您可以使用 javascript 的 xmlHttpRequest
  • 如何在 C# 中异步读取结束进程输出?

    我在 C 中异步读取一个进程的输出时遇到问题 我在这个网站上发现了一些其他类似的问题 但它们并没有真正帮助我 这是我所做的 制定新流程 设置启动信息 文件名 参数 CreateNoWindow true UseShellExecute fa
  • Spark 中的默认分区方案

    当我执行以下命令时 scala gt val rdd sc parallelize List 1 2 3 4 3 6 4 partitionBy new HashPartitioner 10 persist rdd org apache s
  • 如何在 SQL Server 中使用 RANK()

    我使用时遇到问题RANK https msdn microsoft com en us library ms176102 aspx在 SQL Server 中 这是我的代码 SELECT contendernum totals RANK O
  • 使用 Json.format 没有可用的 MyClass 隐式格式

    在 Json format 上使用复杂对象作为另一个对象的属性时出现错误 我有两节课 RoleDTO and 电子邮件邀请DTO 电子邮件邀请DTO has a RoleDTO 所以 我宣布 case class RoleDTO id Op
  • Java正则表达式匹配除

    匹配除特定字符之外的所有字符的正确语法是什么 例如我想匹配除字母之外的所有内容 A Z a z 和数字 0 9 I have string matches A Z a z 0 9 这是不正确的吗 是的 你不需要嵌套 像那样 使用这个代替 A
  • 根据情况启动docker容器

    Problem 我有一个包含 6 个服务的 docker compose yml 当我执行 docker compose up 时 所有 6 个容器都会启动 但我需要 2 个容器来最初开始工作 并根据条件休息 4 个容器 描述 组合中的 6
  • OpenCL 矩阵乘法应该更快?

    我正在尝试学习如何使 GPU 优化 OpenCL 内核 我以使用本地内存中的方形图块进行矩阵乘法为例 然而在最好的情况下 我只得到了约 10 倍的加速 约 50 Gflops 与 numpy dot 相比 5 Gflops 它使用的是 BL
  • 如何使这两个事件的代码简短

    我有以下代码 我怎样才能使它简短 以便它可以通过单击并输入来工作 这样我就不必重复它 document ready function document keypress function e if e which 13 form myfor
  • 如何将存储值分配给隐藏字段

    我有一个模型和商店 我需要为商店中的隐藏字段分配一个值 Ext define loginUser extend Ext data Model fields name id mapping Provider id name name mapp
  • 这个计算Code128条码校验位的代码正确吗?

    根据我对 Code128 条形码 与大多数其他标准条形码类型截然不同 的校验位计算的理解 我下面的代码是正确的 然而 我希望那些可能更了解 有一些经验观察 来自附着在风衣 或实验室 外套上的战壕泥的人进行 健全性检查 这是我的理解 条形码中
  • AngularJs 和 ASP.NET MVC 5 - ng-model 覆盖文本框值

    我有一个使用 ASP NET MVC 5 构建的表单 Html TextBoxFor用我的模型填充表单 例如 在表单导航或服务器端验证失败之后 我现在引入了使用 Angular 的客户端地址查找 这意味着一些表单字段现在用ng model启
  • 如何在R中的approxfun()之后根据y值输入估计x值[重复]

    这个问题在这里已经有答案了 我想用approxfun或类似的方法来估计曲线的函数 然后估计x一个点的值将被赋予一个已知的y value 这是一个简化的示例 y lt seq from 1 to 10 by 1 x lt seq from 0
  • 实体框架的审计跟踪

    我在每个表中都有审计跟踪字段 InsertedBy InsertedDate UpdatedBy 和 UpdatedDate 我构建解决方案以通过覆盖 savechange 来减少冗余 public override int SaveCha