3

目前,我的实体使用如下模型:

public class MyModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public virtual User User { get; set; }
}

这很好用,但我一直看到 CodeFirst 示例,其中为模型中的外部实体显式创建了 Id 属性。这是有道理的,所以我不必延迟加载用户来检索与MyModel实例关联的用户的 id 值。

但是,当我更改MyModel为:

public class MyModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public virtual int UserId { get; set; }
    public virtual User User { get; set; }
}

尝试提交MyModel实例时出现以下异常:

System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "MyModel_User". The conflict occurred in database "mjlunittest", table "dbo.Users", column 'Id'.

为什么我会收到此异常?

4

1 回答 1

4

当您从第一个示例MyModel移至第二个示例时,EF Code-First 约定检测到一个重要更改:

在模型中没有外键属性的第一种情况下,该关系MyModel -> User可选的,因为可以(作为对另一个对象的引用)中的属性为空UserMyModel因此,EF 约定将在数据库中创建一个可为的外键列。

在第二种情况下,您告诉 EF 您的外键是不可为空UserId的类型。因此 EF 约定规则将根据需要考虑关系并在数据库中创建一个不可为空的 Int32 列。intMyModel -> User

如果您创建第二个版本类型的对象MyModel,将其添加到上下文并调用 SaveChanges,您将得到您描述的异常 - 除非您在数据库中有一个带有外键的用户(如果您不这样做,则必须为 0) t 在创建对象时指定另一个值)。创建和保存第一个版本的对象不会抛出此异常,因为这里允许数据库中的外键为null.

如果您希望两个示例的MyModel行为方式相同,您可以在第二个示例中使外键属性为空:

public virtual int? UserId { get; set; }

那么关系在 的两个例子中都是可选MyModel的。

或者您可以User在第一个示例中设置所需的属性:

[Required]
public virtual User User { get; set; }

然后在两个示例中都需要该关系。

于 2011-03-29T23:53:49.747 回答