我有此表,希望跟踪其他表的编辑。
namespace fais.accounting.Models.COA
{
public class coaEdits
{
public string entity_id { get; set; }
public string editor_id { get; set; }
[Display(Name = "Edited on")]
public DateTime occured_on { get; set; } = DateTime.Now;
public User editor { get; set; }
public string entityType { get; set; }
public string entity { get; set; } // If I coaEdits<Tkey> I can't set public Tkey entity, but it should be the object of the entityType's class right?
}
}
我希望该表可以在外键为entity_id
的地方工作。
所有其他表/类都继承了具有导航到coaEdits的类
public class coa_base
{
[Column(Order = 2)]
public string title { get; set; }
[Display(Name = "Entry date")]
public DateTime entry_date { get; set; }
[Required]
[Display(Name = "Last updated")]
public DateTime updated_on { get; set; } = DateTime.Now;
public string creator_id { get; set; } //= @TODO userManage.get_current_user <- how to default?
public User creator { get; set; }
public virtual List<coaEdits> edits { get; set; }
}
其中一个表的示例是
public class budgets : coa_base
{
[Column(Order = 1)]
[Display(Name = "Budget")]
public string budget_id { get; set; }
public virtual List<coa> accounts { get; set; }
}
我跑步时
dotnet ef migrations add setsUpBaseClassModelOnCOA --context ApplicationDbContext
我得到:
migrationBuilder.CreateTable(
name: "coaEdits",
columns: table => new
{
entity_id = table.Column<string>(nullable: false),
editor_id = table.Column<string>(nullable: false),
occured_on = table.Column<DateTime>(nullable: false),
editorId = table.Column<string>(nullable: true),
entity_type = table.Column<string>(maxLength: 200, nullable: false),
// everything below this seems like it should be wrapped up with
// key as entity_id and typed by entity_type, but it is not?
entity = table.Column<string>(nullable: true), // that should be an object? What the?
budgetsbudget_id = table.Column<string>(nullable: true), // should be it should be the entity_id
coaaccount_id = table.Column<string>(nullable: true), // didto
fundsfund_id = table.Column<string>(nullable: true), // didto
// and so on
},
constraints: table =>
{
table.PrimaryKey("PK_coaEdits", x => new { x.entity_id, x.editor_id, x.occured_on });
table.ForeignKey(
name: "FK_coaEdits_coa_budgets_budgetsbudget_id",
column: x => x.budgetsbudget_id,
principalTable: "coa_budgets",
principalColumn: "budget_id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_coaEdits_coa_accounts_coaaccount_id",
column: x => x.coaaccount_id,
principalTable: "coa_accounts",
principalColumn: "account_id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_coaEdits_AspNetUsers_editorId",
column: x => x.editorId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_coaEdits_coa_funds_fundsfund_id",
column: x => x.fundsfund_id,
principalTable: "coa_funds",
principalColumn: "fund_id",
onDelete: ReferentialAction.Restrict);
// and so on
});
在我期望得到的时候:
migrationBuilder.CreateTable(
name: "coaEdits",
columns: table => new
{
entity_id = table.Column<string>(nullable: false),
editor_id = table.Column<string>(nullable: false),
occured_on = table.Column<DateTime>(nullable: false),
editorId = table.Column<string>(nullable: true),
entity_type = table.Column<string>(maxLength: 200, nullable: false),
},
constraints: table =>
{
table.PrimaryKey("PK_coaEdits", x => new { x.entity_id, x.editor_id, x.occured_on });
table.ForeignKey(
name: "FK_coaEdits_coa_budgets_budgetsbudget_id",
column: x => x.entity_id,
principalTable: "coa_budgets",
principalColumn: "budget_id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_coaEdits_coa_accounts_coaaccount_id",
column: x => x.entity_id,
principalTable: "coa_accounts",
principalColumn: "account_id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_coaEdits_AspNetUsers_editorId",
column: x => x.editorId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_coaEdits_coa_funds_fundsfund_id",
column: x => x.entity_id,
principalTable: "coa_funds",
principalColumn: "fund_id",
onDelete: ReferentialAction.Restrict);
// and so on
});
构建器上的流利选项是
builder.Entity<coaEdits>().HasKey(sc => new { sc.entity_id, sc.editor_id, sc.occured_on });
builder.Entity<coaEdits>(b =>
{
b.HasDiscriminator<string>("entityType");
b.Property(e => e.entityType)
.HasMaxLength(200)
.HasColumnName("entity_type");
});
builder.Entity<coa>().ToTable("coa_accounts");
builder.Entity<funds>().ToTable("coa_funds");
// and so on
纠正此问题的最佳方法是什么?有没有更好的方法?缺少的部分是
public string entity { get; set; }
我似乎无法弄清楚如何从鉴别器将其转换为类,这是我希望能够做到的。鉴别符也不必也是键,因此它也将是entity_type
和entity_id
的键
编辑/更新:我正在尝试将该类型应用为这样
public class coaEdits<TKey>
{
public string entity_id { get; set; }
public string editor_id { get; set; }
[Display(Name = "Edited on")]
public DateTime occured_on { get; set; } = DateTime.Now;
public User editor { get; set; }
public string entityType { get; set; }
[NotMapped]
public TKey entity { get; set; }
}
基类如下:
public class coa_base<TKey>
{
[Column(Order = 2)]
public string title { get; set; }
[Display(Name = "Entry date")]
public DateTime entry_date { get; set; }
[Required]
[Display(Name = "Last updated")]
public DateTime updated_on { get; set; } = DateTime.Now;
public string creator_id { get; set; } //= userManage.get_current_user
public User creator { get; set; }
public virtual List<coaEdits<TKey>> edits { get; set; }
}
示例类为
public class budgets : coa_base<budgets>
{
[Column(Order = 1)]
[Display(Name = "Budget")]
public string budget_id { get; set; }
public virtual List<coa> accounts { get; set; }
}
将其用于流利的构建器选项
builder.Entity<coaEdits<IKey>>().HasKey(sc => new { sc.entity_id, sc.editor_id, sc.occured_on });
builder.Entity<coaEdits<IKey>>(b =>
{
b.HasDiscriminator<string>("entityType");
b.Property(e => e.entityType).HasColumnName("entity_type");
});
但是我现在收到此错误
实体类型'coaEdits'需要定义主键。
但这是我认为的
builder.Entity<coaEdits<IKey>>().HasKey(sc => new { sc.entity_id, sc.editor_id, sc.occured_on });
如果我用所有硬编码的代码对其进行测试,则在哪里进行
builder.Entity<coaEdits<budgets>>() . .
我得到一个要创建的coaEdits<budgets>
表。
如果我尝试用builder.Entity<coaEdits<budgets>>().ToTable("coa_edits");
来反击该表名,则它说另一个coaEdits<funds>
和coaEdits<budgets>
无法共享表,因为它们不共享主键,但我认为他们entity_id
其他更新:继续使用coaEdits<TKey>
方法,以便public string entity { get; set; }
获得类型,我认为如果流利的api不能设置主键,那我会尝试使用属性来解决此问题,但这产生了此错误
实体类型
'coaEdits<budgets>'
具有使用数据注释定义的复合主键。要设置复合主键,请使用fluent API。
仅从此开始。
public class coaEdits<TKey>
{
[Key]
public string entity_id { get; set; }
[Key]
public string editor_id { get; set; }
// and so on
其他信息:如果我以我认为应该正确设置表的方式更改迁移,则会遇到另一个在上下文中没有意义的错误。在这里,我将首先设置coaEdits表
migrationBuilder.CreateTable(name: "coaEdits", columns: table => new {
entity_id = table.Column<string>(nullable: true)
, editor_id = table.Column<string>(nullable: true)
, occured_on = table.Column<DateTime>(nullable: false)
, entity_type = table.Column<string>(nullable: false)
}, constraints: table => {
table.PrimaryKey("PK_coaEdits", x => x.occured_on);
table.ForeignKey(name: "FK_coaEdits_AspNetUsers_editorId", column: x => x.editor_id
, principalTable: "AspNetUsers", principalColumn: "Id"
, onDelete: ReferentialAction.Restrict);
table.ForeignKey(name: "FK_coaEdits_coa_budgets_entity_id", column: x => x.entity_id
, principalTable: "coa_budgets", principalColumn: "budget_id"
, onDelete: ReferentialAction.SetNull);
table.ForeignKey(name: "FK_coaEdits_coa_funds_entity_id", column: x => x.entity_id
, principalTable: "coa_funds", principalColumn: "fund_id"
, onDelete: ReferentialAction.SetNull);
// and so on
});
实体预算示例是这样设置的
migrationBuilder.CreateTable(
name: "coa_budgets",
columns: table => new
{
entry_date = table.Column<DateTime>(nullable: false),
updated_on = table.Column<DateTime>(nullable: false),
title = table.Column<string>(nullable: true),
creator_id = table.Column<string>(nullable: true),
budget_id = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_coa_budgets", x => x.budget_id);
table.ForeignKey(
name: "FK_coa_budgets_AspNetUsers_creator_id",
column: x => x.creator_id,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
但是当我运行dotnet ef database update --context ApplicationDbContext
时会导致此错误
列“ coa_budgets.budget_id”的长度或比例与引用外键“ FK_coaEdits_coa_budgets_entity_id”中的列“ coaEdits.entity_id”的长度或比例不同。参与外键关系的列必须定义为相同的长度和比例。
完整错误是:
Failed executing DbCommand (21ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [coaEdits] (
[entity_id] nvarchar(max) NULL,
[editor_id] nvarchar(max) NULL,
[occured_on] datetime2 NOT NULL,
[entity_type] nvarchar(max) NOT NULL,
CONSTRAINT [PK_coaEdits] PRIMARY KEY ([occured_on]),
CONSTRAINT [FK_coaEdits_AspNetUsers_editor_id] FOREIGN KEY ([editor_id]) REFERENCES [AspNetUsers] ([Id]) ON DELETE NO ACTION,
CONSTRAINT [FK_coaEdits_coa_budgets_entity_id] FOREIGN KEY ([entity_id]) REFERENCES [coa_budgets] ([budget_id]) ON DELETE SET NULL,
CONSTRAINT [FK_coaEdits_coa_funds_entity_id] FOREIGN KEY ([entity_id]) REFERENCES [coa_funds] ([fund_id]) ON DELETE SET NULL,
CONSTRAINT [FK_coaEdits_coa_objects_entity_id] FOREIGN KEY ([entity_id]) REFERENCES [coa_objects] ([object_id]) ON DELETE SET NULL,
CONSTRAINT [FK_coaEdits_coa_programs_entity_id] FOREIGN KEY ([entity_id]) REFERENCES [coa_programs] ([program_id]) ON DELETE SET NULL,
CONSTRAINT [FK_coaEdits_coa_projects_entity_id] FOREIGN KEY ([entity_id]) REFERENCES [coa_projects] ([project_id]) ON DELETE SET NULL,
CONSTRAINT [FK_coaEdits_coa_accounts_entity_id] FOREIGN KEY ([entity_id]) REFERENCES [coa_accounts] ([account_id]) ON DELETE SET NULL,
CONSTRAINT [FK_coaEdits_coa_subobjects_entity_id] FOREIGN KEY ([entity_id]) REFERENCES [coa_subobjects] ([subobject_id]) ON DELETE SET NULL,
CONSTRAINT [FK_coaEdits_coa_subfunds_entity_id] FOREIGN KEY ([entity_id]) REFERENCES [coa_subfunds] ([subfund_id]) ON DELETE SET NULL
);
System.Data.SqlClient.SqlException (0x80131904): Column 'coa_budgets.budget_id' is not the same length or scale as referencing column 'coaEdits.entity_id' in foreign key 'FK_coaEdits_coa_budgets_entity_id'. Columns participating in a foreign key relationship must be defined with the same length and scale.
在阅读完所有内容后,我已经设置了所有匹配的外键。.entity_id是[entity_id] nvarchar(max) NULL,
,预算是[budget _id] nvarchar(max) NULL,
,所以我不确定SQL为什么会抛出该错误。