我有一个定义如下的语言
模型:
public class Language
{
[JsonProperty("iso_639_1")]
public string Iso { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
public override bool Equals(object obj)
{
if (!(obj is Language))
{
return false;
}
return ((Language)obj).Iso == Iso;
}
public override int GetHashCode()
{
return Iso.GetHashCode();
}
}
这是在模型 Movie
中使用的 ICollection<Language> SpokenLanguages
。我使用收集到的信息来填充我的数据库。当多个电影使用相同的语言时,我希望能够重复使用 Languages
表中已有的条目。
下面的代码通过重复使用现有类型并添加新类型来实现此目的:
var localLanguages = context.Languages.ToList();
var existingLanguages = localLanguages.Union(movie.SpokenLanguages);
var newLanguages = localLanguages.Except(existingLanguages).ToList();
newLanguages.AddRange(existingLanguages);
movie.SpokenLanguages = newLanguages;
这个方法是能够正常工作的,但它看起来很丑陋,也不符合EF的规范。我正在研究如何将现有模型附加到EF并使其自动重复使用,但我似乎无法使其正常工作——我最终得到了这个错误信息:
“由于另一个实体具有相同的主键值,因此无法附加类型为 'Models.Movies.Language' 的实体。当在图形中的任何实体具有冲突的关键字值时,如果使用'Attach'方法或将实体的状态设置为 'Unchanged' or 'Modified',则可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的关键值。在这种情况下,请使用 'Add' 方法或 'Added' 实体状态来跟踪该图形,然后根据需要将非新实体的状态设置为 'Unchanged' 或 'Modified'。”
相关代码如下:
var localLanguages = context.Languages.ToList();
foreach (var language in movie.SpokenLanguages)
{
if (localLanguages.Contains(language))
{
context.Languages.Attach(language);
// no difference between both approaches
context.Entry(language).State = EntityState.Unchanged;
}
}
把状态设置为Unchanged
或Modified
没有区别。我收到的JSON响应是:
{
"iso_639_1": "en",
"name": "English"
}
这些值与数据库中的现有值完全相同,这两个字段都是如此。
每次插入数据库时都会创建一个新的上下文并处理它。
我该如何让EF重复使用现有的语言条目,而不是自己筛选它们?
MovieLanguages
表中有多对多的关系。如果我简单地省略了一种语言,它将不会被记录在这个表中,而这正是在我的Movie
模型中拥有该导航属性的全部意义所在。 - Jeroen Vannevel