首页 > 解决方案 > 如何使用 EF Core Fluent API 设计动态表数据结构?

问题描述

我想将数据存储在 SQL 表中。我的结构看起来像一个 Excel 表(或任何类型的表)。交叉点中有包含列、行和单元格的表格。我的域模型是:

public class Table {
    public int Id { get; set; }
    public List<Column> Columns { get; set; }
    public List<Row> Rows { get; set; }
}

public class Column {
    public string Name { get; set; }
    public int TableId { get; set; }
    
    public Table Table { get; set; }
}

public class Row {
    public int Id { get; set; }
    public List<Cell> Cells { get; set; }
    public int TableId { get; set; }
    
    public Table Table { get; set; }
}

public class Cell {
    public int RowId { get; set; }
    public string ColumnName { get; set; }
    public int TableId { get; set; }
    
    public string CellValue { get; set; }
    
    public Column Column { get; set; }
    public Row Row { get; set; }
}

棘手的部分是在单元格中,我在其中使用带有RowId,ColumnName和的复合键TableId

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Table>()
        .HasMany(x => x.Columns)
        .WithOne(x => x.Table)
        .HasForeignKey(x => new { x.TableId, x.Name });
        
    builder.Entity<Column>()
        .HasKey(x => new { x.TableId, x.Name });
        
    builder.Entity<Row>()
        .HasOne(x => x.Table)
        .WithMany(x => x.Rows);
    builder.Entity<Row>()
        .HasMany(x => x.Cells)
        .WithOne(x => x.Row)
        .HasForeignKey(x => new { x.RowId, x.ColumnName, x.TableId });
    
    builder.Entity<Cell>()
        .HasKey(x => new { x.RowId, x.ColumnName, x.TableId });
}

不幸的是,在尝试将表添加到数据库时出现异常。

InvalidOperationException:从 'Cell.Row' 到 'Row.Cells' 的关系具有外键属性 {'RowId' : int, 'ColumnName' : string, 'TableId' : int} 不能定位主键 {'Id' : int } 因为它不兼容。为此关系配置一个主键或一组兼容的外键属性。

我将我的示例 repo 发布到了 GitHub,也许它有助于理解和测试。 https://github.com/kodaniel/TableDbContextSample

当我使用简单的 Id PK 字段而不是复合键时,此示例工作正常,但我认为 Cell.Id 属性完全没有必要,因为 Table.Id、Column.Name 和 Row.Id 显然可以识别特定的 Cell . 所以我想这种方法应该可行,唯一的问题是我不知道我在哪里弄乱了模型构建。

标签: c#asp.net-coreentity-framework-core

解决方案


推荐阅读