【问题标题】:EF Core 6: Find name of Intermediate tableEF Core 6:查找中间表的名称
【发布时间】:2022-01-19 19:07:28
【问题描述】:

从 EF Core 5 开始,无需显式定义中间表即可轻松生成多对多表。但是,我希望能够获得两个实体之间自动生成的中间表的名称。例如,假设我有两个实体:

public class Foo
{
    public int FooId { get; set; }
    public ICollection<Bar> Bars { get; set; }
}

public class Bar
{
    public int BarId { get; set; }
    public ICollection<Foo> Foos { get; set; }
}

我创建了一个包含这两个实体的 DbContext,创建了一个迁移,然后将其应用到我的数据库中,我希望生成三个表:

  • Foos
  • Bars
  • FooBars

有没有办法,给定FooBar(或Foo.BarsBars.Foos),找到自动生成的表名FooBars的名称?

【问题讨论】:

  • 你试过检查 IModel 吗? context.Model
  • 是的,我今天下午一直在探索 IModel,但还没有找到我要找的东西。

标签: c# entity-framework-core ef-core-6.0


【解决方案1】:

不确定这是否有帮助,但您始终可以选择命名包含多对多关系的中间表。

因此,如果让 EF Core 处理中间表,则不能指定名称,但可以在定义时调用 UsingEntity&lt;T&gt; 以指定表名。

public class AppDbContext : DbContext
{
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Bar> Bars { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=FoobarmanytomanySample;Trusted_Connection=True;MultipleActiveResultSets=true")
                      .UseLazyLoadingProxies();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Entry>()
                    .HasMany(x => x.Foos)
                    .WithMany(x => x.Bars)
                    .UsingEntity<Dictionary<string, object>>(
                        "FooBars",
                        x => x.HasOne<Tag>().WithMany(),
                        x => x.HasOne<Entry>().WithMany());
    }
}

【讨论】:

  • 我希望避免这种情况,但我很欣赏这个建议。谢谢。
【解决方案2】:

终于找到了办法。没有异常处理,我不确定它有多脆弱,但它适用于我的 DbContext。一个例子:

public class Foo
{
    public int FooId { get; set; }
    public ICollection<Bar> Bars { get; set; }
}

public class Bar
{
    public int BarId { get; set; }
    public ICollection<Foo> Foos { get; set; }
}

public class AppDbContext : DbContext
{
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Bar> Bars { get; set; }

    public string GetIntermediateTableNameForEntityProperty(Type entity, string propertyName)
    {
        IEntityType entityType = base.Model.FindEntityType(entity);
        ISkipNavigation propSkipNavigation = entityType.GetSkipNavigations().Single(x => string.Equals(x.Name, propertyName));
        IForeignKey foreignKey = propSkipNavigation.ForeignKey;
        IProperty foreignKeyProperty = foreignKey.Properties.Single();
        string intermediateTableName = foreignKeyProperty.DeclaringEntityType.Name;
        return intermediateTableName;
    }
}

用法:

public class Baz
{
    private readonly AppDbContext _appDbContext;

    public Baz(AppDbContext appDbContext)
    {
        _appDbContext = appDbContext;
    }

    public void SomeMethod()
    {
        var intermediateTableName = _appDbContext.GetIntermediateTableNameForEntityProperty(typeof(Foo), nameof(Foo.Bars));
        // intermediateTableName = "FooBars"
    }
}

【讨论】:

    猜你喜欢
    • 2022-12-20
    • 1970-01-01
    • 2022-01-10
    • 2018-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-02-27
    • 2021-06-17
    相关资源
    最近更新 更多