我有一个表需要通过其Id
列绑定到另一个表,并通过其(Id, Code)
列绑定到第三个表。我可以使用主键和唯一索引在 SQL Server 中轻松完成,但不知道如何在 Entity Framework 中实现它。
如果我在两列上都添加了[Key]
属性,那么我就无法创建第一个关系。
否则,如果我只申请一个[Key]
,那么我就无法建立第二关系。
有没有解决方法?
答案 0 :(得分:2)
好的,我可以使用 Fluent API 制作所需数量的密钥。它现在有效。
更详细:
在商业术语中,我有一个Form
对象,其字段就像在html文档中一样 - 类型为input, choice, text, radiogroup
等。
我更喜欢在单独的表中存储强类型的字段数据,但是表单需要知道哪些字段用于维护它们的唯一顺序。
所以在数据库中我有表:
Form
- 包含表格的名称和说明
FormField
- (每个表单0到多行)包含 FormId , FieldType 和 OrderNo 。通过将(FormId,OrderNo)设置为唯一,我保持正确的顺序。
诀窍是键入的字段本身存储在不同的表中,如InputField
,ChoiceField
,NumberField
等。我希望它们绑定到父FormField行,如0或删除父行时,不允许它们丢失
如果它是简单的父子关系,我可以使用标准FK,但在这里我有variuos子表。
为了使其一致,在 SQL Server 中,我在父FormField
表和FK中创建了一个复合PK (FormId,FieldType) as {em>(FormId,FieldType)在所有子表中FieldType
设置为常量计算值(例如InputField
表中为0,ChileField
表中为1等)。
因此,对于单个FormField
和多个子特定类型的表,我有一个良好的父子约束
在EF方法中,要制作复合FK,您需要将所有相应的字段设置为键,因此您将[Key]属性放在两个字段上。
但是,如果特定于类型的表需要拥有自己的子项(例如ChoiceField
具有ChoiceOptions
),并且您已经有了复合键,那么您需要使用现有的复合键或添加新的keyset(仅包含 Id 字段)。
所以,我的问题是让ChoiceField表有两组键:一组用于父FieldForm行,第二组用于ChoiceOption子表。简单 - 用于ChoiceOption子表。
使用Fluent API我可以添加第二个键。
这是我的EF模型:
[Table("Form")]
public class Form : IEntity
{
[Key, Column("FormID")]
public int Id { get; set; }
[Required, StringLength(50)]
public string Name { get; set; }
public ICollection<FormField> FormFields { get; set; }
}
[Table("FormField")]
public class FormField : IEntity
{
[Key, Column("FormFieldID", Order = 0)]
public int Id { get; set; }
[Key, Column(Order = 1)]
public FieldType FieldType { get; set; }
[ForeignKey("Form")]
public int FormId { get; set; }
public int OrderNo { get; set; }
public virtual Form Form { get; set; }
public virtual AddressField AddressField { get; set; }
public virtual ChoiceField ChoiceField { get; set; }
public virtual DateTimeField DateTimeField { get; set; }
// etc
}
[Table("ChoiceField")]
public class ChoiceField : BaseField, IEntity
{
[Key, ForeignKey("FormField"), Column("FormFieldID", Order = 0)] // these keys are for parent FormField table
public int Id { get; set; }
[Key, ForeignKey("FormField"), Column(Order = 1)]
public FieldType FieldType { get; set; }
public virtual FormField FormField { get; set; }
public ICollection<ChoiceFieldOption> ChoiceFieldOptions { get; set; }
}
[Table("ChoiceFieldOption")]
public class ChoiceFieldOption : IEntity
{
[Key, Column("ChoiceFieldOptionID")]
public int Id { get; set; }
[ForeignKey("ChoiceField")] // this FK are bound to simple ChoiceField.Id key defined in fluent API
public int ChoiceFieldId { get; set; }
[Required, StringLength(50)]
public string Option { get; set; }
public int OrderNo { get; set; }
public virtual ChoiceField ChoiceField { get; set; }
}
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Form>();
var eFormField = modelBuilder.Entity<FormField>();
var eChoiceField = modelBuilder.Entity<ChoiceField>();
// here I add a second Key for ChoiceField table
eChoiceField.HasKey(cf => new { cf.Id });
var eChoiceFieldOption = modelBuilder.Entity<ChoiceFieldOption>();
modelBuilder.Entity<AddressField>();
modelBuilder.Entity<DateTimeField>();
// ...
}