实体框架:唯一(不是主键)的复合外键



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存储在不同表中,例如InputFieldChoiceFieldNumberField等父行被删除。
如果这是简单的父母关系,我可以使用标准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>();
    // ...
    }

最新更新