EF Code-First 一对一关系:多重性在关系中的角色 * 中无效 [英] EF Code-First One-to-one relationship: Multiplicity is not valid in Role * in relationship

查看:25
本文介绍了EF Code-First 一对一关系:多重性在关系中的角色 * 中无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试执行以下操作:

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 关联.您仍然可以有多个 Class2 对象引用同一个one Class1 对象.此外,您的模型不保证引用 Class1Class2 也被这个 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 关联的常用方法是为主体 实体和依赖 实体分别创建一个表,其中依赖表中的主键也是主体的外键:

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.

流畅的映射

要在 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;}
}

无法在模型中配置备用外键属性,因为唯一涉及的 FK 必须是依赖项的主键.

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 一对一关系:多重性在关系中的角色 * 中无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆