实体框架:外键上唯一的(没有主键)母公司领域母公司、实体、主键、框架

2023-09-05 03:34:27 作者:﹌ 仅冇旳骄傲

我有一个需要它的编号列被绑定到其它表的表,并通过其(ID,$第三个表C $ C)列。我可以很容易做到在的 SQL服务器的同时使用一个主键和一个唯一索引,但不知道如何实现它的实体框架的。

I have a table that needs to be bound to another table by its Id column, and to the third table by its (Id, Code) columns. I can easily do in in SQL Server using both a primary key and a unique index, but have no idea how to implement it in Entity Framework.

如果我把 [关键] 属性然后我无法创建的第一关系。

If I put [Key] attribute on both columns then I'm unable to create a first relationship.

否则,如果我只应用一个 [关键] 然后,我不能让第二个关系。

Otherwise, if I only apply one [Key] then I cannot make second relationship.

有没有什么解决方法吗?

Is there any workaround?

推荐答案

好吧,我可以为使用需要作出尽可能多的按键的流利的API 的。它的工作原理吧。

Ok, I was able to make as many keys as needed using Fluent API. It works now.

更详细的: 在业务方面,我有一个表格对象,它具有字段就像在HTML文档 - 类型输入,选择,文本,RadioGroup中等 我prefere存储领域的强类型,在不同的表中的数据,但形式需要知道哪些字段是在保持自己独特的秩序。

More detailed: In business-terms, i have a Form object that has Fields just like in html document - of types input, choice, text, radiogroup etc. I prefere to store fields data strongly typed, in separate tables, but the form needs to know what fields are in to maintain their unique order.

因此​​,在数据库中,我有表:

So in the database i have tables:

表格 - 包含窗体的名称和描述 FormField - (0到多行每个表单)中包含的 FormId 的的FieldType 和 OrderNo 。通过设置的(FormId,OrderNo)的独特的我保持正确的顺序。

Form - contains Form's name and description FormField - (0 to many rows for each form) contains FormId, FieldType and OrderNo. By setting (FormId, OrderNo) to unique I maintain the right order.

诀窍在于类型字段itselves都存储在不同的表像 InputField ChoiceField NumberField 等。我希望他们被束缚于母公司FormField行如0或1比1,不要让当父行被删除他们迷路。 如果是简单的父子关系,我可以使用标准的FK,但在这里我有variuos子表。

The trick is that the typed fields itselves are stored in different tables like InputField, ChoiceField, NumberField etc. I want them to be tied to the parent FormField rows like 0 or 1 to 1 and not to allow them to get lost when parent row is deleted. If it was simple parent-child relation, i could use standard FK, but here i have variuos child tables.

为使这一切一致,在 SQL服务器的我创建了一个复合PK的(FormId,的FieldType)的父 FormField 表和FKS为的(FormId,的FieldType)的其中的FieldType 设置为常数的计算值的所有子表中(比如0在 InputField 表1中的 ChileField 表等)。 因此,我已经有了一个良好的亲子约束单个 FormField 和多个子特定类型的表。 在EF的方法,使复合FK所有你需要的相应字段是钥匙,所以你穿上这两个领域的[关键]属性。 但是如果你的特定类型的表都需要有自己的孩子(如 ChoiceField ChoiceOptions ),你已经有一个复合键,那么你就需要既可以使用现有的组合键或添加新键集(仅编号的领域)。

To make it all consistent, in the SQL Server i've created a composite PK (FormId, FieldType) in the parent FormField table and FKs as (FormId, FieldType) in all child tables where FieldType is set to constant computed value (say 0 in the InputField table, 1 in the ChileField table etc). Thus i've got a good parent-child constraint for a single FormField and multiple child specific-typed tables. In EF approach, to make a composite FK you need all the corresponding fields to be Keys, so you put the [Key] attribute on both fields. But if your type-specific table needs to have its own children (like ChoiceField has its ChoiceOptions), and you already have a composite Key, then you need either use the existing composite key or add a new keyset (with only Id field).

所以,我的问题是使ChoiceField表使其具有两套密钥:1,复合材料,对父FieldForm行,和第二,简单 - 为ChoiceOption子表 用流利的API,我可以添加第二个关键。

So, my problem was to make ChoiceField table to have two sets of keys: one, composite, for the parent FieldForm row, and the second, simple - for the ChoiceOption child table. Using Fluent API I was able to add a second key.

这是我的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>();
    // ...
    }