EF Code-First 一对一关系:多重性在 Role * in relationship 中无效

EF Code-First One-to-one relationship: Multiplicity is not valid in Role * in relationship(EF Code-First 一对一关系:多重性在 Role * in relationship 中无效)
本文介绍了EF Code-First 一对一关系:多重性在 Role * in relationship 中无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 对象.此外,您的模型不保证引用 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 关联的常用方法是为 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 中无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)