gpt4 book ai didi

c# - 新的重复对象违反主键

转载 作者:行者123 更新时间:2023-11-30 12:12:18 26 4
gpt4 key购买 nike

我正在使用代码优先方法的 Entity Framework 5。

我有两个彼此具有多对多关系的类,MoviePersonMovie 通过 CharacterPerson 相关。每个 Movie 可以有多个角色。

public class Movie {
public int Id { get; set; }
public string Title { get; set; }
public int? Year { get; set; }
public virtual ICollection<Character> Characters { get; set; }

public Movie() {
Characters = new HashSet<Character>();
}
}

public class Character {
public string Name { get; set; }
public virtual Movie Movie { get; set; }
public virtual Person Person { get; set; }
}

public class Person {
public int Id { get;set; }
public string Name { get; set; }
public virtual ICollection<Character> Characters { get; set; }

public Person() {
Characters = new HashSet<Character>();
}
}

有时,一部电影可以有一个Person扮演多个Character。在这种情况下尝试添加 Movie 时遇到问题...

假设 Movie1 有 2 个角色,均由 Person1 扮演。保存更改时,EF 将从 Character1 开始,并发现数据库中不存在 Person1 并将该 Person 插入到 dbo.Person。然后它会转到 Character2,但会发现 Person1 已经存在,并且会引发主键冲突。

在我的 MovieRepository 中,我有一个 Add(Movie entity) 方法。我遍历 Movie 的每个 Character 并检查数据库中是否存在相关的 Person。如果他们这样做,那么我将 Person 属性设置为现有的 Person。这在正常情况下有效,但如果 Person 根本不存在,那么我不确定如何避免 PK 违规,这就是我的问题:)

public class MovieRepository : Repository<Movie> {
public MovieRepository(MovieContext context) : base(context) {}

public override void Add(Movie entity) {
foreach (var character in entity.Characters) {
var person = Context.People.FirstOrDefault(p => p.Id == character.Person.Id);
if (person != null)
character.Person = person;
}
Context.Movies.Add(entity);
}
}

只是为了添加更多信息。我使用带有工作单元模式的存储库模式来保存我的存储库和上下文。所以 UnitOfWork 类负责 SaveChanges()

尝试在 MovieRepository.Add() 中执行此操作可能不是完成此任务的最佳/适当方法。我期待着任何和所有的建议。

为了进一步说明,我从 Rotten Tomatoes API 获取数据,json 看起来像这样......

{data : [{
Id: 12345,
Title: 'Movie1',
Year: 2010,
Character: [{
Name: 'Character1',
Person: { Id: 1, Name: 'Person1' }
},{
Name: 'Character2',
Person: { Id: 2, Name: 'Person2' }
}]
}]}

最佳答案

您如何为 2 个字符发送同一个人对象?它是否已经有一个唯一的 key 集?否则它们将被 Entity Framework 视为两个独立的对象。如果您已经定义了一个唯一键,您可以先检查本地集合,然后检查上下文,或者将此人添加到上下文中。

// Only works if the unique key is already defined.
var person =
Context.People.Local.FirstOrDefault(p => p.Id == character.Person.Id) ??
Context.People.FirstOrDefault(p => p.Id == character.Person.Id);

if (person == null)
Context.People.Add(person);

但是我建议您可能会更改您的聚合,以便此方法根本不会添加人员。您可以将添加一个人和添加一个“电影”(作为 {Movie, Character} 的集合作为 2 个单独的操作)处理。如果您分别管理人员(这样一个人可以有零个或多个字符),这将是有意义的。

这会更有意义,因为电影并不“拥有”人物,它是多对多关系。

例如在 UI 中:添加带有角色的电影时,您可以选择扮演该角色的人,或者此时添加一个新角色。因此,当发送要保存的电影时,您将始终有一个 character.PersonId,它将指向已保存的人物对象。

虽然这当然可能不适用于您的特定场景,但这只是一个想法。

关于c# - 新的重复对象违反主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13886813/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com