使用特定数据跟踪数据库插入

时间:2017-03-30 08:47:41

标签: c# asp.net sql-server entity-framework

我正在维护ASP.NET MVC应用程序,它通过Entity Framework与MS SQL数据库进行通信。

有一段时间,我们正在观察实体更新或插入数据库时​​使用特定字段为空的情况。

此字段可能为空,但我们强烈怀疑,大多数情况不应发生。我想挂钩一些调试代码来记录这些尝试的所有实例。

问题是我不知道,我应该在哪里做。

  • 在代码的很多地方插入和更新实体;
  • 我可能会覆盖其DBSet后代的Insert和Update方法,但我不会间接捕获更改(例如从数据库中检索实体,更改它并调用SaveChanges())。

我在哪里可以放置代码,这些代码能够访问特定实体上对数据库的所有写入修改?

2 个答案:

答案 0 :(得分:4)

我相信您正在寻找ChangeTracking的{​​{1}}属性。

我使用类似的方法通过捕获已更改/添加/删除的内容来在实体上构建历史记录。

为此,您可以在DbContext中覆盖DbContext方法,然后拦截正在更改的条目。

请务必在覆盖结束时致电SaveChanges()以实际保存所有更改。

例如,假设您的DbContext名为MyAppDbContext

base.SaveChanges();

答案 1 :(得分:0)

我认为Audit.NET库及其EntityFramework extension可以帮助您满足此类要求,因为您需要对代码进行最少的更改。

例如,假设您有以下背景:

public class YourContext : DbContext
{
    public DbSet<Post> Posts { get; set; }
}

并且您希望在Date表的Posts字段即将设置为NULL时审核更改。

首先,您需要更改上下文的基类以继承Audit.EntityFramework.AuditDbContext

public class YourContext : AuditDbContext
{
    public DbSet<Post> Posts { get; set; }
}

然后,这只是启动配置的问题,例如:

// Configure the event output to save logs as files
Audit.Core.Configuration.Setup().UseFileLogProvider(_ => _.Directory(@"D:\Temp"));   

// Add a custom action to filter out the events
Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
    var ef = scope.Event.GetEntityFrameworkEvent();
    var interested = ef.Entries.Any(e => e.Table == "Posts" 
                                    && new[] { "Insert", "Update" }.Contains(e.Action)
                                    && e.ColumnValues["Date"] == null);
    // Discard the audit event if we are not interested in (i.e. only log when Date is null)
    if (!interested)
    {
        scope.Discard();
    }
});

// Configure EF extension
Audit.EntityFramework.Configuration.Setup() 
    .ForContext<YourContext>()      // Your context class type
        .UseOptIn()                 // OptIn to include specific entities 
        .Include<Post>();           // Audit only the Post entity

使用此配置,它将在您的文件系统上生成json文件,其内容类似于以下内容:

{
  "EventType": "YourContext",
  "Environment": {
    "UserName": "Federico",
    "MachineName": "HP",
    "DomainName": "Domain",
    "Exception": null,
    "Culture": "en-US"
  },
  "StartDate": "2017-09-10T16:11:05.7987461-05:00",
  "EndDate": "2017-09-10T16:11:10.4458419-05:00",
  "Duration": 4647,
  "EntityFrameworkEvent": {
    "Database": "Blogs",
    "Entries": [
      {
        "Table": "Posts",
        "Action": "Insert",
        "PrimaryKey": {
          "Id": 11
        },
        "ColumnValues": {
          "Id": 11,
          "BlogId": 7,
          "Content": "post content",
          "Date": null,
          "Title": "post-test"
        },
        "Valid": true
      }
    ],
    "Result": 2,
    "Success": true
  }
}