65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 EF Core 的影子属性实现通用审计字段

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2017 年 3 月 22 日

CPOL

1分钟阅读

viewsIcon

11733

了解如何使用 Entity Framework 的新影子属性功能,轻松为实体实现通用的审计字段

EF Core 最酷的功能之一是你可以定义不存在于 Entity 类中的属性。它们被称为影子属性。在使用 EF6 时,我需要一些每个实体都会扩展的通用审计字段。例如,当表中的某一行被更新时,当某一行被创建时,行的版本是什么等等。由于 EF6 中没有影子属性的概念,我和许多其他开发人员所做的是创建一个包含这些通用字段的接口,并在需要的实体中实现该接口。然后通过更改跟踪添加或更新这些字段的值。就像这样

public interface IAuditable
{
    DateTime Created { get; set; }
    DateTime Modified { get; set; }
}

在需要时实现接口

public class Person : IAuditable
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }

    public DateTime Created { get; set; }
    public DateTime Modified { get; set; }
}

通过实体更改跟踪更新审计字段的值

public override int SaveChanges()
{
    foreach (var auditableEntity in ChangeTracker.Entries<IAuditable>())
    {
        if (auditableEntity.State == EntityState.Added ||
            auditableEntity.State == EntityState.Modified)
        {
            auditableEntity.Entity.Modified = DateTime.Now;

            if (auditableEntity.State == EntityState.Added)
            {
                auditableEntity.Entity.Created = DateTime.Now;
            }
        }
    }
    return base.SaveChanges();
}

与其创建一个接口并在每个实体中实现它,我们还可以将审计字段添加为影子字段。这只是另一种方式,不是首选方式。因此,在设计实体时要非常谨慎。

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    builder.Entity<Person>().Property<DateTime?>("Created");
    builder.Entity<Person>().Property<DateTime?>("Modified");
}

这里,数据类型后的问号表示数据库中映射的列类型可以为 null 值。 如果你没有指定,对于 datetime 列类型,ef core 会设置一个默认的 datetime 字符串,有时可能会让人困惑。

由于影子属性不是具体实体的一部分,因此访问它们及其处理值的方式与通常的方式大不相同。

public override int SaveChanges()
{
    var modifiedEntries = ChangeTracker.Entries()
        .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);

    foreach (EntityEntry entry in modifiedEntries)
    {
        var entityType = entry.Context.Model.FindEntityType(entry.Entity.GetType());

        var modifiedProperty = entityType.FindProperty("Modified");
        var createdProperty = entityType.FindProperty("Created");

        if (entry.State == EntityState.Modified && modifiedProperty != null)
        {
            entry.Property("Modified").CurrentValue = DateTime.Now;
        }

        if (entry.State == EntityState.Added && createdProperty != null)
        {
            entry.Property("Created").CurrentValue = DateTime.Now;
        }
    }

    return base.SaveChanges();
}

就这样!这就是你使用影子属性以不同的方式为实体实现审计字段的方法。但使用它们与否由你决定。

© . All rights reserved.