i有一个表,需要通过其Id
列将其绑定到另一个表,以及通过其(Id, Code)
列的第三个表。我可以使用主键和唯一索引轻松地在 sql Server 中进行操作,但不知道如何在 Entity Framework 中实现它。
如果我将[Key]
属性放在两个列上,那么我将无法创建第一个关系。
否则,如果我只应用一个[Key]
,那么我就无法建立第二个关系。
有解决方法吗?
好吧,我能够使用 fluent api 来制作尽可能多的键。现在起作用。
更详细:
在业务范围内,我有一个像html文档一样具有字段的 Form
对象 - 类型input, choice, text, radiogroup
等。
我希望在单独的表格中存储字段数据,但形式需要知道哪些字段来维护其独特的顺序。
所以在数据库中我有表:
Form
-包含表单的名称和描述
FormField
-(每种形式的许多行)包含 formid , fieldType 和 orderno 。通过设置(Formid,orderno)到唯一我维护正确的顺序。
诀窍是,键入字段itselves存储在不同表中,例如InputField
,ChoiceField
,NumberField
等父行被删除。
如果这是简单的父母关系,我可以使用标准FK,但是在这里我有variuos child桌子。
使其全部保持一致,在 sql Server中,我已经创建了一个复合PK (FormID,FieldType) 在parent FormField
表和fks中为(formid,fieldType)在所有子表中FieldType
设置为常数计算值(例如InputField
表中的0,ChileField
表中的1个)。
因此,我对单个FormField
和多个儿童特异性表都有很好的父母约束。
在EF方法中,要制作一个复合FK,您需要所有相应的字段是键,因此您将[键]属性放在两个字段上。
但是,如果您的特定于类型的表需要有自己的孩子(例如ChoiceField
具有ChoiceOptions
),并且您已经拥有一个复合键,那么您需要使用现有的复合键或添加新密钥集(仅使用 iD字段)。
所以,我的问题是要使Choice Field表具有两组键:一组,复合,用于父野外壁行,而第二个键则是ChoiceOption Child桌子。
使用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>();
// ...
}