实体框架:一个或多个外键属性不可为空



我有一个非常复杂的数据库模型。我的程序计算一些data+db entriesmodifies+generates new entries以更新+插入数据库。

当我使用数据库上下文插入条目时,一切正常。但是当我尝试保存更改时:

{"操作失败:无法更改关系,因为一个或多个外键属性不可为空。对关系进行更改时,相关的外键属性将设置为 null 值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

我在SO上看到了太多关于这个话题的问题。但我的问题是模型太复杂了,我无法跟踪问题。实体框架 6 没有给我任何有关问题来源、关系名称、...

有没有办法从实体框架获得更多帮助以找到问题的根源?

你必须分析你的对象来解决这个问题。

这里有一些简单的代码来解释你的Exception

static void Main()
{
using (MyDbContext ctx = new MyDbContext())
{
// Build a new object
MyClass o = new MyClass() { Id = 1, ChildObject = null };
// Add it to your Context (It's not in the DB yet!)
ctx.MyObjects.Add(o);
// Write all changes (the new object) to the Db
ctx.SaveChanges();
}
}
// You got some DbContext with a DbSet pointing to your Table "MyTable"
public class MyDbContext : DbContext
{
public DbSet<MyClass> MyObjects { get; set; }
}
// You've got a class to map your table to some nice object.
[Table("MyTable")]
public class MyClass
{
// Some column..
[Key]
public int Id { get; set; }
// And some ForeignKey! Which maps a column with the Id to an object.
[ForeignKey("ChildObjectId")]
public MyClass ChildObject { get; set; }
}

在此示例中,我创建一个上下文,添加一个对象并保存更改(创建插入到表中(。

1st:在 SaveChanges 时发生异常,因为属性"ChildObject"可以设置为 null,因为我们对该属性没有任何限制。

2nd:异常是数据库异常。您的程序(可能(运行正确。但是 qour Db 告诉你,不允许在 MyTable 中有一个没有引用 ChildObject 的行。

您必须问自己数据库是否配置错误(使列可为空(或程序是否忘记设置子项。

我希望你看到:你必须深入研究你的代码。你的"完成模型"遇到了问题,你必须解决它。

请考虑读取上下文的 SQL 日志。示例:ctx.Log = Console.WriteLine;(这里没有工作室,但我认为我应该是这样的(。

通过这种方式,您可以获取最后一个 SQL 查询并在 Db 上运行它以获得更好的错误输出。

我手动递归地为我的对象的每个子级执行此过程:

if(parent.child!=null){
parent.childId=parent.child.id;
parent.child=null;
}

通过这种方式,您可以从父对象中删除每个子对象,只保留 Id,因此 EntityFramework 不会进行任何错误的插入,并且关系仍然存在。

由于引用的表值直接与主表的 c# 对象内的主表相关联,因此出现问题

CREATE TABLE [dbo].[MainTable](
[MainId] [int],
[Name] [varchar](50) NOT NULL
);
CREATE TABLE [dbo].[ReferedTable](
[ReferId] [int],
[MainId] [int] NOT NULL,
[Name] [varchar](50) NULL
);

并且对外键有约束

using (EF context = new EF())
{
var values = context.MainTable.Include("ReferedTable");
var referedValues = values.ReferedTable.ToList();
foreach (var value in referedValues)
{
context.ReferedTable.DeleteObject(value);
}
context.SaveChanges();
}

如果您尝试执行以下操作,那么错误就会出现。因为引用表连接到主表,如果你在其中进行更改并保存,EF 将引发错误

using (EF context = new EF())
{
var values = context.MainTable.Include("ReferedTable");
var referedValues = values.ReferedTable.ToList();
foreach (var value in referedValues)
{
values.ReferedTable.Remove(value);
}
context.SaveChanges();
}

最新更新