我有一个需要它的编号
列被绑定到其它表的表,并通过其(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>();
// ...
}