目前我的实体使用如下模型:
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
是可选的,因为属性 User
在MyModel
可以 - 作为对另一个对象的引用 - 为空。因此,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/