【问题标题】:ef core new dbcontext executes OnModelCreating only onceef core new dbcontext 只执行一次 OnModelCreating
【发布时间】:2020-03-06 08:09:36
【问题描述】:

我们定期更改数据库数据(每两周至每月一次)。 通常必须使用最新的数据,但在某些特殊情况下,旧的数据是必要的。

atm 必须使用哪个版本的当前信息存储在另一个表中。

数据库看起来像这样,版本化的 Schema-Names 下有相同的表。

YYYYMMDD+Revision

myshema_202001011
    table1
myshema_202002011 and so on
    table1
myshema_202003011 and so on
    table1

我已经构建了一个带有两个 DbContext 类的 Aspnet 核心 (2.2) 服务, 一种用于获取当前版本的静态架构,另一种用于访问这些数据的不断变化的架构。

静态 DbContext 工作正常。

问题是,即使我将不断变化的 contaxt 与 using like 一起使用,

using (var _context = new ChangingDbContext()){}

构造函数和OnConfiguring 每次都会执行,但OnModelCreating 方法只执行一次。 这会导致更新到当前架构。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");

    modelBuilder.Entity<my_table>(entity =>
    {
        entity.HasKey(e => e.key_adr);
        entity.ToTable("mytable", $"myshema{mySchemaVersion}");
    }); 
}

有没有人知道如何获得每次执行 OnModelCreating 的“真正”新上下文? 或者也许另一种解决方案如何处理那些不断变化的架构?

【问题讨论】:

标签: c# entity-framework asp.net-core ef-core-2.2


【解决方案1】:

继续我的评论。下面的 db 表设计允许您或用户根据需要向对象添加任意数量的新字段。而且我认为它提供了最灵活的结构。

假设在电子商务系统中,我们为产品提供 3 个字段(名称、代码、价格)。但我们也允许用户将他们的自定义字段添加到他们的产品中(例如 Promotion1Price、Promotion2Price、Discount ......)

产品(产品 ID、名称、代码、价格)

CUSTOMEFIELD (FieldId, FieldName, FieldType)

PRODUCT_CUSTOMFIELD(ProductId、FieldId、FieldValue)

如果这不符合您的目的,请告诉我。

【讨论】:

  • 表格本身并不是真正的问题。表更改(新列和内容)提前一个月就知道了,因此它们甚至在相关之前就可以很容易地处理。唯一阻止我的是 OnModelCreating 只运行一次,因此我的上下文的表模式不会改变。我有一个为 DbContext 设置模式名称的方法,但是当 OnModelCreating 仅在它不会被更新时运行。
  • 我想说的是。您的根本问题是表需要经常更改。那么正确的解决方案是设计允许频繁更改的表格。您的解决方案是设计一个经常更改的代码。而且我不认为这是一个好的设计。因为我看不到将更改表的问题转换为更改代码的任何价值。希望这是有道理的。
【解决方案2】:

这个答案解决了https://stackoverflow.com/a/41985226/6692289

引用示例以防被删除。

派生的 DbContext 将其 ModelCacheKey(和工厂)替换为 一个自定义的。

class MyDbContext : DbContext
{
    public MyDbContext(string schema)
    {
        Schema = schema;
    }

    public string Schema { get; }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options
            .UseSqlServer("...")
            .ReplaceService<IModelCacheKeyFactory, MyModelCacheKeyFactory>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema(Schema);

        // ...
    }
}

创建具有特定键的上下文的工厂。

class MyModelCacheKeyFactory : IModelCacheKeyFactory
{
    public object Create(DbContext context)
        => new MyModelCacheKey(context);
}

每个上下文的自定义 ModelCacheKey。

class MyModelCacheKey : ModelCacheKey
{
    string _schema;

    public MyModelCacheKey(DbContext context)
        : base(context)
    {
        _schema = (context as MyDbContext)?.Schema;
    }

    protected override bool Equals(ModelCacheKey other)
        => base.Equals(other)
            && (other as MyModelCacheKey)?._schema == _schema;

    public override int GetHashCode()
    {
        var hashCode = base.GetHashCode() * 397;
        if (_schema != null)
        {
            hashCode ^= _schema.GetHashCode();
        }

        return hashCode;
    }
}

并使用上下文之类的。

using (var _myContext = new MyDbContext(_schemaNameToUse)
{
}

【讨论】:

    猜你喜欢
    • 2019-04-30
    • 1970-01-01
    • 2022-08-21
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    • 2021-08-06
    相关资源
    最近更新 更多