问题描述
我正在尝试执行以下操作:
I'm attempting to do the following:
public class class1
{
public int Id {get;set;}
[ForeignKey("Class2")]
public int Class2Id {get;set;}
public virtual Class2 Class2 {get;set;}
}
public class class2
{
public int Id { get; set;}
[Required]
public virtual int Class1Id {get;set;}
[Required]
[ForeignKey("Class1Id")]
public Class1 Class1 {get;set;}
}
但是,每次我尝试迁移数据库时,都会收到以下错误:
However every time I try to migrate my database I get the following error:
Class1_Class2_Target: : 多重性在角色中无效关系Class2_Class1"中的Class2_Class1_Target".因为Dependent Role 属性不是关键属性,上限从属角色的多重性必须是*".
Class1_Class2_Target: : Multiplicity is not valid in Role 'Class2_Class1_Target' in relationship 'Class2_Class1'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
这可能是什么问题?
推荐答案
您的模型不是 1:1 关联.您仍然可以有 many Class2
对象引用同一个 one Class1
对象.此外,您的模型不保证引用 Class1
的 Class2
也被此 Class1
对象引用 - Class1
可以引用任何 Class2
对象.
Your model is not a 1:1 association. You can still have many Class2
objects referring to the same one Class1
object. Also, your model doesn't guarantee that a Class2
referring to a Class1
is also referred back by this Class1
object — Class1
can refer to any Class2
object.
在 SQL 中保证(某种程度上)1:1 关联的常用方法是为 principal 实体创建一个表,为 从属 实体创建一个表,其中依赖表中的主键也是主体的外键:
The common way to guarantee (sort of) a 1:1 association in SQL is to have a table for the principal entity and one for the dependent entity where the primary key in the dependent table also is a foreign key to the principal:
(这里Class1
是主体)
现在在关系数据库中,这仍然不能保证 1:1 关联(这就是我说有点"的原因).这是一个 1:0..1 关联.Class1
可能没有 Class2
.事实上,真正的 1:1 关联在 SQL 中是不可能的,因为没有一种语言结构可以在不同的表中同步插入两行.1:0..1 是我们得到的最接近的值.
Now in a relational database, this still doesn't guarantee a 1:1 association (that's why I said 'sort of'). It's a 1:0..1 association. There can be a Class1
without a Class2
. The truth is, genuine 1:1 associations are impossible in SQL, because there is no language construct that inserts two rows in different tables synchronously. 1:0..1 is the closest we get.
Fluent 映射
要在 EF 中为这种关联建模,您可以使用 fluent API.这是执行此操作的标准方法:
To model this association in EF you can use the fluent API. Here's the standard way to do it:
class Class1Map : EntityTypeConfiguration<Class1>
{
public Class1Map()
{
this.HasKey(c => c.Id);
this.Property(c => c.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.HasRequired(c1 => c1.Class2).WithRequiredPrincipal(c2 => c2.Class1);
}
}
在上下文中:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new Class1Map());
}
这是你的课程的左边:
public class Class1
{
public int Id {get;set;}
public virtual Class2 Class2 {get;set;}
}
public class Class2
{
public int Id {get;set;}
public virtual Class1 Class1 {get;set;}
}
无法在模型中配置备用外键属性,因为唯一涉及的外键必须是依赖项的主键.
There is no way to configure alternate foreign key properties in the model, because the only FK involved has to be the dependent's primary key.
这个模型的奇怪之处在于 EF 不会阻止您创建(和保存)一个 class1
对象没有一个 class2
.我认为 EF 应该能够在保存更改之前验证此要求,但显然它没有.同样,有一些方法可以删除 class2
对象而不删除其 class1
父对象.所以这个 HasRequired
- WithRequired
对并不像看起来那么严格(而且应该如此).
The strange thing about this model is that EF doesn't stop you from creating (and saving) a class1
object without a class2
. I think EF should be capable of validating this requirement before saving changes, but, apparently, it doesn't. Likewise, there are ways to delete a class2
object without deleting its class1
parent. So this HasRequired
- WithRequired
pair is not as stringent as it looks (and should be).
数据注释
在代码中做到这一点的唯一方法是通过数据注释.(当然数据库模型仍然无法执行 1:1)
The only way to get this right in code is by data annotations. (Of course the database model will still not be able to enforce 1:1)
public class Class1
{
public int Id {get;set;}
[Required]
public virtual Class2 Class2 {get;set;}
}
public class Class2
{
[Key, ForeignKey("Class1")]
public int Id {get;set;}
[Required]
public virtual Class1 Class1 {get;set;}
}
[Key, ForeignKey("Class1")]
注释告诉 EF Class1
是主体实体.
The [Key, ForeignKey("Class1")]
annotation tells EF that Class1
is the principal entity.
数据注解在许多 API 中都发挥着作用,这可能是一个诅咒,因为每个 API 都选择自己的子集来实现,但在这里它派上了用场,因为现在 EF 不仅使用它们来设计 数据模型,还用于验证实体.现在,如果您尝试在没有 class2
的情况下保存 class1
对象,您将收到验证错误.
Data annotations play a role in many APIs, which can be a curse, because each API chooses its own subset to implement, but here it comes in handy, because now EF not only uses them to design the data model, but also to validate entities. Now if you try to save a class1
object without a class2
you'll get a validation error.
这篇关于EF Code-First 一对一关系:多重性在 Role * in relationship 中无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!