Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多对一关系导致DbUpdateException_C#_Entity Framework_Entity Framework 6_One To Many - Fatal编程技术网

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添加支持字段是什么意思?然后只“初始化”一次,然后保持相同的值?是的,但不完全相同。初始化并保持相同的对象,在设置条形图时更改它。