c# - 为什么将显式外部 ID 列添加到我的 EF4.1 CodeFirst 实体会导致外键约束冲突?

标签 c# entity-framework code-first entity-framework-4.1

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

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'.

为什么我会收到此异常?

最佳答案

当您从 MyModel 的第一个示例移动时对于第二个示例,EF Code-First 约定检测到一个重要的变化:

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

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

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

如果你想要 MyModel 的两个例子行为方式与第二个示例中可以使外键属性可为空的方式相同:

public virtual int? UserId { get; set; }

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

或者你可以制作User第一个示例中需要的属性:

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

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

关于c# - 为什么将显式外部 ID 列添加到我的 EF4.1 CodeFirst 实体会导致外键约束冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5479797/

相关文章:

c# - 防止在创建具有 Entity Framework 关系的其他实体时复制现有对象

c# - 类名中有 "+"?

C# XmlWriter 和无效的 UTF8 字符

c# - Entity Framework 计数效率

c# - 关联父子数据模型对象的最佳方法是什么?

c# - 什么是更好的设计/实践 : Nullable property or 1 value property and 1 bool "has" property?

c# - MVC 模型 - 应用程序 (EF) 中的一个或多个 dbcontext

asp.net - Entity Framework CTP5,代码优先。多对多级联删除

c# - 如何将每个功能或方法分配给一个按钮?

c# - 为什么这是进食内存?