C# 多对一关系导致DbUpdateException
我有以下问题: 我有一个类C# 多对一关系导致DbUpdateException,c#,entity-framework,entity-framework-6,one-to-many,C#,Entity Framework,Entity Framework 6,One To Many,我有以下问题: 我有一个类Foo,它有一个IBars的列表。由于它是一个接口,并且可以有许多实现,实体框架无法将此属性本身保存到数据库中。为了解决这个问题,我刚刚创建了另一个不同类型的列表属性(BarDatabaseObject),它很容易序列化。其思想是,IBar的具体实现/实例只是序列化到DB上的单个字段中,而该表中唯一的其他字段是Id 然而,这不起作用。我得到一个UpdateException: System.Data.Entity.Infrastructure.DbUpdateExcep
Foo
,它有一个IBar
s的列表。由于它是一个接口,并且可以有许多实现,实体框架无法将此属性本身保存到数据库中。为了解决这个问题,我刚刚创建了另一个不同类型的列表属性(BarDatabaseObject
),它很容易序列化。其思想是,IBar
的具体实现/实例只是序列化到DB上的单个字段中,而该表中唯一的其他字段是Id
然而,这不起作用。我得到一个UpdateException
:
System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> System.Data.Entity.Core.UpdateException: An error occurred while updating the entries. See the inner exception for details.
---> System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK_dbo.BarDatabaseObject'.
Cannot insert duplicate key in object 'dbo.BarDatabaseObject'.
The duplicate key value is (a3450574-2d93-4c90-bcdf-88779d18068c).
我100%肯定我没有重复的密钥,因为我只向列表中添加了一个IBar
对象,而且之前数据库是空的
经过一些调查,我发现实体框架多次调用属性BarsDatabaseObjects
。由于我总是在那里创建一个包含新对象(但值完全相同!)的新列表,实体框架在第一次访问属性时没有意识到它是同一个对象,并假设它必须是一个新的BarDatabaseObject
,因此尝试将其添加到数据库中
我怎样才能解决这个问题?这个场景对我来说似乎很简单(甚至没有那么“特别”)
谢谢你的帮助
internal class Program
{
private static void Main(string[] args)
{
var dbContext = ....;
Foo foo = ...; //initialize it, with all properties
dbContext.Foos.Add(foo); //exception occurs here!
dbContext.SaveChanges();
}
}
public class Foo
{
public Guid Id { get; set; }
//cannot be saved by entity framework, because it's an interface
[NotMapped]
public List<IBar> Bars { get; set; }
public virtual List<BarDatabaseObject> BarsDatabaseObjects
{
get
{
return Bars.Select(c => new BarDatabaseObject
{
Id = c.Id,
ImplementationsAsJson = JsonSerializer.Serialize(c)
}).ToList();
}
set
{
Bars = value.Select(c => JsonSerializer.Deserialize<IBar>(c.ImplementationsAsJson))
.ToList();
}
}
// many implementations of this interface exists
public interface IBar
{
Guid Id { get; }
}
public class BarDatabaseObject
{
public Guid Id { get; set; }
public string ImplementationsAsJson { get; set; }
public Guid? FooId { get; set; }
[ForeignKey(nameof(FooId))]
public virtual Foo Foo { get; set; }
}
内部类程序
{
私有静态void Main(字符串[]args)
{
var dbContext=。。。。;
Foo Foo=…;//使用所有属性初始化它
dbContext.Foos.Add(foo);//此处发生异常!
dbContext.SaveChanges();
}
}
公开课Foo
{
公共Guid Id{get;set;}
//无法由实体框架保存,因为它是一个接口
[未映射]
公共列表栏{get;set;}
公共虚拟列表BarsDatabaseObjects
{
得到
{
返回条。选择(c=>NewBarDatabaseObject
{
Id=c.Id,
ImplementationsAsJson=JsonSerializer.Serialize(c)
}).ToList();
}
设置
{
bar=value.Select(c=>JsonSerializer.Deserialize(c.ImplementationSASSJSON))
.ToList();
}
}
//这个接口有很多实现
公共接口IBar
{
Guid Id{get;}
}
公共类BarDatabaseObject
{
公共Guid Id{get;set;}
公共字符串实现SasJSON{get;set;}
公共Guid?FooId{get;set;}
[外键(名称(FooId))]
公共虚拟Foo Foo{get;set;}
}
为BarsDatabaseObjects添加支持字段是什么意思?然后只“初始化”一次,然后保持相同的值?是的,但不完全相同。初始化并保持相同的对象,在设置栏时更改。为BarsDatabaseObjects添加支持字段是什么意思?然后只“初始化”一次,然后保持相同的值?是的,但不完全相同。初始化并保持相同的对象,在设置条形图时更改它。