如何向 EF Core 中的所有实体添加相同的列?

2023-12-12

想象一下,我想向我的所有实体添加 IsDeleted 列或一些审核列。我可以创建一个基类,我的所有实体都将继承该基类,这将解决我的问题,但是我无法指定创建列的顺序,因此我最终会在实体的字段之前得到所有审核字段,这是我不想要的。我希望他们位于桌子的末尾。

在实体框架的标准版本中,我们可以通过使用指定列顺序的注释来做到这一点。然而,目前 EF core 还不存在这样的事情。

我可以使用 OnModelCreating() 方法上的 Fluent api 来完成此操作,问题是我只知道如何为每个实体单独执行此操作,这意味着我必须为我拥有的每个实体编写相同的代码。

有什么方法可以为我的所有实体通用地做到这一点吗?某种 for 循环迭代在我的 dbcontext 上的 DbSet 中注册的所有实体?


您的问题标题是关于向多个实体添加相同的属性。但是,您实际上知道如何实现这一点(使用基本类型)并且您的actual问题是如何确保这些属性位于生成的表列的最后。

尽管现在列顺序并不重要,但我将展示一个您可能比基本类型更喜欢的替代方案,并且also将公共属性放置在表的末尾。它利用阴影属性:

影子属性是未在 .NET 实体类中定义但在 EF Core 模型中为该实体类型定义的属性。

大多数时候,审核属性在应用程序中不需要太多可见性,因此我认为影子属性正是您所需要的。这是一个例子:

我有两节课:

public class Planet
{
    public Planet()
    {
        Moons = new HashSet<Moon>();
    }
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Moon> Moons { get; set; }
}

public class Moon
{
    public int ID { get; set; }
    public int PlanetID { get; set; }
    public string Name { get; set; }
    public Planet Planet { get; set; }
}

正如您所看到的:他们没有审计属性,他们是非常刻薄和精干的 POCO。 (顺便说一句,为了方便起见,我把IsDeleted与“审核属性”一起使用,尽管它不是一个并且可能需要另一种方法)。

也许这就是这里的主要信息:类模型不关心审计问题(单一职责),都是 EF 的事。

审核属性作为影子属性添加。由于我们想为每个实体执行此操作,因此我们定义了一个基础IEntityTypeConfiguration:

public abstract class BaseEntityTypeConfiguration<T> : IEntityTypeConfiguration<T>
    where T : class
{
    public virtual void Configure(EntityTypeBuilder<T> builder)
    {
        builder.Property<bool>("IsDeleted")
            .IsRequired()
            .HasDefaultValue(false);
        builder.Property<DateTime>("InsertDateTime")
            .IsRequired()
            .HasDefaultValueSql("SYSDATETIME()")
            .ValueGeneratedOnAdd();
        builder.Property<DateTime>("UpdateDateTime")
            .IsRequired()
            .HasDefaultValueSql("SYSDATETIME()")
            .ValueGeneratedOnAdd();
    }
}

具体配置源自该基类:

public class PlanetConfig : BaseEntityTypeConfiguration<Planet>
{
    public override void Configure(EntityTypeBuilder<Planet> builder)
    {
        builder.Property(p => p.ID).ValueGeneratedOnAdd();
        // Follows the default convention but added to make a difference :)
        builder.HasMany(p => p.Moons)
            .WithOne(m => m.Planet)
            .IsRequired()
            .HasForeignKey(m => m.PlanetID);
        base.Configure(builder);
    }
}

public class MoonConfig : BaseEntityTypeConfiguration<Moon>
{
    public override void Configure(EntityTypeBuilder<Moon> builder)
    {
        builder.Property(p => p.ID).ValueGeneratedOnAdd();
        base.Configure(builder);
    }
}

这些应该添加到上下文的模型中OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new PlanetConfig());
    modelBuilder.ApplyConfiguration(new MoonConfig());
}

这将生成具有列的数据库表InsertDateTime, IsDeleted and UpdateDateTime最后(与何时base.Configure(builder)被称为,顺便说一句),尽管在that顺序(按字母顺序)。我想这已经足够接近了。

为了使图片更完整,以下是如何在SaveChanges覆盖:

public override int SaveChanges()
{
    foreach(var entry in this.ChangeTracker.Entries()
        .Where(e => e.Properties.Any(p => p.Metadata.Name == "UpdateDateTime")
                 && e.State != Microsoft.EntityFrameworkCore.EntityState.Added))
    {
        entry.Property("UpdateDateTime").CurrentValue = DateTime.Now;
    }
    return base.SaveChanges();
}

小细节:我确保插入实体时数据库默认设置两个字段(见上文:ValueGeneratedOnAdd(),因此排除了添加的实体),因此不会因客户端时钟稍微偏离而导致令人困惑的差异。我认为更新总是会晚一些。

并设置IsDeleted您可以将此方法添加到上下文中:

public void MarkForDelete<T>(T entity)
    where T : class
{
    var entry = this.Entry(entity);
    // TODO: check entry.State
    if(entry.Properties.Any(p => p.Metadata.Name == "IsDeleted"))
    {
        entry.Property("IsDeleted").CurrentValue = true;
    }
    else
    {
        entry.State = Microsoft.EntityFrameworkCore.EntityState.Deleted;
    }
}

...或者转向建议的机制之一进行转换EntityState.Deleted to IsDeleted = true.

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

如何向 EF Core 中的所有实体添加相同的列? 的相关文章

随机推荐

  • 如何仅更改 ttk.Entry 的一侧边框宽度?

    我正在尝试使用 tkinter 网格和 ttk 条目显示数独布局 也许 我没有使用正确的方法来实现它 我想知道 ttk 条目的样式选项是否有任何方法可以更改一侧的边框 我已经应用了这个功能 def grid layout parent s
  • 如何更改 Asp.net Identity 3.0 中的表名称?

    如何更改 ASP net Identity 3 0 中的表名称 我已经搜索过 但没有找到任何有关 Identity 3 0 的可行文章 和这个如何更改 asp net Identity 3 vnext 使用的表名称 不管用 您可以通过使用扩
  • 向表中插入数据时出现问题

    sqlite3 数据库 sqlite3 stmt 语句 NSString dPath NSBundle mainBundle resourcesPath stringByAppendingPathComponent UserData sql
  • 如何检测 Excel 是否通过自动化启动(VSTO Addin 上下文)

    Context 我正在运行 VSTO Excel 应用程序上下文插件 当 MS Excel 由其他进程启动以在可见模式下实现自动化时 我也会加载我的插件 所以现在 有必要知道 MS Excel 是否是由其他自动化进程启动的 例如 创建对象
  • 使用 Google Analytics 跟踪 AJAX 请求

    我正在更改网站的很大一部分以使用 jQuery Address 的深度链接 AJAX 功能 我正在使用像这样的 URImysite com page1 subpage 等等 我读过很多关于使用以下方式跟踪流量的内容 gaq push 功能
  • 如何在 JBoss 应用程序服务器中创建数据源 [关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 任何人都可以提供在 JBoss 服务器 5 0 中使用 Oracle 数据库创建数据源的
  • 如何自动显示类的所有属性及其在字符串中的值? [复制]

    这个问题在这里已经有答案了 想象一个具有许多公共属性的类 由于某种原因 不可能将此类重构为更小的子类 我想添加一个 ToString 覆盖 它返回以下内容 Property 1 Value of property 1 n Property
  • java外部类编译会影响内部类吗

    我需要给 websphere 打一个补丁 我有一个主要的java类 它有三个内部类 我对主类的代码更改很少 但对任何内部类没有更改 现在我的问题是我是否需要将所有内部类以及主类文件作为补丁的一部分或单独提供主类就足够了 这不是一个权威的答案
  • JavaScript Array.length 返回 0

    I have javascript Array that looks like 问题是Object mappings有 3 个元素清楚地打印在控制台中console log 但是当我尝试查找它返回的数组长度时0 我尝试对数组进行字符串化 它
  • 在 Excel 函数中将十六进制字符串转换为 base64

    我有一长串十六进制值要转换为 base64 我正在寻找一个简单的格式单元格函数 例如 Hex2b64 Hexstring 它将接受任意长度的十六进制字符 我一直在使用http home paulschou net tools xlate 手
  • 并行触发异步请求,但使用 rxjs 按顺序获取结果

    例如 使用 jquery ajax 并行获取 5 个页面 当第 2 页返回时 不执行任何操作 当 page1 返回时 对 page1 和 page2 执行一些操作 assume there is some operator that can
  • Android 列表视图中的 OnItemClickListener 与 OnclickListener

    由于代码的原因 这会很长 所以我有一个关于 OnItemclickListener 与 OnclickListener 的问题 这里我有两个代码 每个代码都有效 所以是否有优先使用这两个代码之一或者我可以使用任何人 这是 OnItemCli
  • 如何让我的动画更加流畅 Android

    我有一个应用程序 有一个球在屏幕上运行 当球到达一半时 应用程序会记录一些音频 计算 FFT 并进行一些额外的分析 这是由 Asynctask 处理的 但是动画仍然短暂地卡顿 有人对如何使其运行更流畅有任何建议吗 Thanks 代码如下 i
  • Protractor - 在启动我的测试规范之前执行登录脚本

    这里的基本问题是我最初尝试登录 启动我的应用程序 然后运行所有规范 事实证明NOT是一个好方法 我无法弄清楚的是 Why navpanel spec js下面首先运行 在登录和启动 js 文件之前 换句话说 如果我在 navpanel sp
  • 有没有办法在android平台上自动播放视频?

    我读了数十亿个关于堆栈溢出的论坛和帖子 但什么也没有 当我找到解决方案或类似的东西时 就不再工作了 我尝试使用 Google API 但什么也没有 我可以在 IOS 本机播放器中自动播放视频 将直接 mp4 链接放在标签 上 但在 Andr
  • 如何使用JavaScript控制音频元素

    首先 我尝试不使用默认的 html5 标准控件 如果可能的话我很乐意使用 jQuery 但我暂时将其删除 因为我不确定问题是什么 目前我只是想有一个播放按钮 单击后会播放一 些音乐 该按钮将更改为暂停按钮 一旦点击这个暂停按钮 音乐就会明显
  • BottomNavigationView 不存在

    我正在尝试将 navigationeditor 与底部导航视图一起使用 但似乎底部导航视图只是导致问题的原因 这是我的 xml
  • 将平面数组中的每个字符串复制 N 次

    我想将每个值重复 3 次并按正确的顺序排列 应使用其自身的 3 个副本来代替每个原始元素 给定以下一维字符串数组 chars a b c 所以结果是 duplicatedChars a a a b b b c c c 我尝试过与str re
  • Gradle 如何从 apk 中排除文件

    我将密钥库存储在资产目录中 如何在构建中排除它以创建 apk 我以这种方式尝试过 但仍然存在 android packagingOptions exclude META INF LICENSE txt exclude assets keys
  • 如何向 EF Core 中的所有实体添加相同的列?

    想象一下 我想向我的所有实体添加 IsDeleted 列或一些审核列 我可以创建一个基类 我的所有实体都将继承该基类 这将解决我的问题 但是我无法指定创建列的顺序 因此我最终会在实体的字段之前得到所有审核字段 这是我不想要的 我希望他们位于