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

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

问题描述

我尝试执行以下操作:

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中的Role
'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关联。您仍然可以有多个 Class1 对象指向同一个 $ c> object。此外,您的模型不能保证 Class2 引用 Class1 $ c> Class1 object - 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 是主体)

现在在关系数据库中, t保证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不会阻止你创建保存)a 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 )] 注释告诉EF Class1 是主体。

The [Key, ForeignKey("Class1")] annotation tells EF that Class1 is the principal entity.

数据注释在许多API中扮演一个角色,这可能是一个诅咒,因为每个API选择自己的子集来实现,但在这里它派上用场,因为现在EF不仅使用它们来设计数据模型但也可以验证实体。现在,如果您尝试保存 class1 对象而不使用 class2 ,您会收到验证错误。

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

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