“附加类型T的实体失败,因为相同类型的另一个实体已经具有相同的主键值”

杰罗恩·范内维尔

我有Language这样定义模型:

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'或' 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;
    }
}

将状态设置为UnchangedModified不会有所不同。我收到的JSON响应是

{
    "iso_639_1": "en",
    "name": "English"
}

这些值与数据库中两个字段中的值完全相同。

数据库中的每次插入都会创建一个新的上下文并进行处理。

我如何才能让EF重复使用现有的语言条目,而不必亲自筛选?

杰罗恩·范内维尔

我已经编辑了模型,因此它现在包含一个字段Id并将其用作主键。其他所有内容,包括平等比较,都保持不变。现在,我收到一条不同的错误消息,该消息可能会进一步阐明该问题:

{“INSERT语句与FOREIGN KEY约束“ FK_dbo.MovieLanguages_dbo.Languages_LanguageId”冲突。冲突发生在数据库“ MoviePicker”,表“ dbo.Languages”,列“ Id”中。该语句已终止。”}

附加信息:保存不公开外键属性为其关系的实体时发生错误。EntityEntries属性将返回null,因为无法将单个实体标识为异常的来源。通过在实体类型中公开外键属性,可以简化保存时的异常处理。有关详细信息,请参见InnerException。

我在datacontext中记录了SQL语句,这是最后执行的语句:

INSERT [dbo].[MovieLanguages]([MovieId], [LanguageId])
VALUES (@0, @1)

-- @0: '2' (Type = Int32)  
-- @1: '0' (Type = Int32)

这表明LanguageIdId表中的字段Language)没有填写。这是有道理的,因为默认情况下它是0,我所做的就是将它附加到EF配置中。这不会使其假定已经存在的对象的值,从而导致FK约束错误,因为它试图创建对ID不存在的ID 0的引用。

知道了这一点,我将自己拥有的和我打算做的事情结合在一起。首先,我查看该语言是否已经存在于数据库中。如果不是,一切都保持正常,我只需插入即可。如果已经在其中,则将其ID分配给新Language对象,分离现有对象并附加新对象。

本质上,我交换了EF不能跟踪的对象。如果它在注意到对象相等时自行执行此操作将非常有帮助,但是直到这样做之前,这是我想出的最好的方法。

var localLanguages = _context.Languages.ToList();
foreach (var language in movie.SpokenLanguages)
{
    var localLanguage = localLanguages.Find(x => x.Iso == language.Iso);
    
    if (localLanguage != null)
    {
        language.Id = localLanguage.Id;
        _context.Entry(localLanguage).State = EntityState.Detached;
        _context.Languages.Attach(language);
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类常见问题

ASP.NET MVC-附加类型为“ MODELNAME”的实体失败,因为相同类型的另一个实体已经具有相同的主键值

来自分类Dev

EF,Automapper异常,“附加类型...的实体失败,因为相同类型的另一个实体已经具有相同的主键值”

来自分类Dev

附加“ModelName”类型的实体失败,因为另一个相同类型的实体已经具有相同的主键值

来自分类Dev

为什么会出现此异常“附加类型为'Model'的实体失败,因为相同类型的另一个实体已经具有相同的主键值。”

来自分类Dev

附加类型为“XXX”的实体失败,因为同一类型的另一个实体已具有相同的主键值

来自分类Dev

附加“ X”类型的实体失败,因为另一个相同类型的实体

来自分类Dev

带有AutoMapper的通用工作单元和存储库模式引发异常“相同类型的另一个实体已经具有相同的主键值”

来自分类Dev

无法跟踪实体类型“ x”的实例,因为已经跟踪了具有相同的{'a','b'}键值的另一个实例

来自分类Dev

EF Core:无法跟踪实体类型的实例,因为另一个具有相同键值的实例

来自分类Dev

在EF 6中更新现有数据会引发异常-“ ...相同类型的实体已经具有相同的主键值。”

来自分类Dev

无法跟踪实体类型 <T> 的实例,因为已跟踪另一个具有相同 {'Id'} 键值的实例

来自分类Dev

无法跟踪实体类型“ TestType”的实例,因为已经跟踪了具有相同键的该类型的另一个实例

来自分类Dev

“如何修复“实体类型的实例”无法跟踪,因为另一个具有键值“{TypeId: 1}”的实例已被跟踪。

来自分类Dev

无法跟踪实体类型“个人资料”的实例,因为已经跟踪了另一个键值为“ {Id:1087}”的实例

来自分类Dev

TypeScript:如何使用变量推断的类型在类外部定义具有相同类型的另一个变量

来自分类Dev

无法跟踪,因为另一个实例具有相同的键值

来自分类常见问题

Hibernate在另一个实体列表中不包括与实体类型相同的子实体

来自分类Dev

无法加载,因为已经加载了另一个具有相同文件的 AssetBundle

来自分类Dev

如何编写一种方法,该方法接受类型为x的数组以及与该数组具有相同类型的另一个变量

来自分类Dev

将一个结构复制到另一个具有相同成员和不同类型的结构

来自分类Dev

如何将键值对引用从一个映射复制到另一个相同类型的映射?

来自分类Dev

一个实体引用 2 个相同实体类型的实体关系?

来自分类Dev

查询以过滤具有相同非主键值的行,然后从 Oracle 中的结果中排除具有另一个空列的记录

来自分类Dev

从相同类型的另一个对象更新Entity Framework对象

来自分类Dev

ASP.NET MVC链接到相同类型的另一个对象

来自分类Dev

从相同类型的另一个对象更新Entity Framework对象

来自分类Dev

ASP.NET MVC链接到相同类型的另一个对象

来自分类Dev

声明与另一个信号相同类型的信号 (VHDL)

来自分类Dev

使用 by 委托给相同类型的另一个对象甚至不编译

Related 相关文章

  1. 1

    ASP.NET MVC-附加类型为“ MODELNAME”的实体失败,因为相同类型的另一个实体已经具有相同的主键值

  2. 2

    EF,Automapper异常,“附加类型...的实体失败,因为相同类型的另一个实体已经具有相同的主键值”

  3. 3

    附加“ModelName”类型的实体失败,因为另一个相同类型的实体已经具有相同的主键值

  4. 4

    为什么会出现此异常“附加类型为'Model'的实体失败,因为相同类型的另一个实体已经具有相同的主键值。”

  5. 5

    附加类型为“XXX”的实体失败,因为同一类型的另一个实体已具有相同的主键值

  6. 6

    附加“ X”类型的实体失败,因为另一个相同类型的实体

  7. 7

    带有AutoMapper的通用工作单元和存储库模式引发异常“相同类型的另一个实体已经具有相同的主键值”

  8. 8

    无法跟踪实体类型“ x”的实例,因为已经跟踪了具有相同的{'a','b'}键值的另一个实例

  9. 9

    EF Core:无法跟踪实体类型的实例,因为另一个具有相同键值的实例

  10. 10

    在EF 6中更新现有数据会引发异常-“ ...相同类型的实体已经具有相同的主键值。”

  11. 11

    无法跟踪实体类型 <T> 的实例,因为已跟踪另一个具有相同 {'Id'} 键值的实例

  12. 12

    无法跟踪实体类型“ TestType”的实例,因为已经跟踪了具有相同键的该类型的另一个实例

  13. 13

    “如何修复“实体类型的实例”无法跟踪,因为另一个具有键值“{TypeId: 1}”的实例已被跟踪。

  14. 14

    无法跟踪实体类型“个人资料”的实例,因为已经跟踪了另一个键值为“ {Id:1087}”的实例

  15. 15

    TypeScript:如何使用变量推断的类型在类外部定义具有相同类型的另一个变量

  16. 16

    无法跟踪,因为另一个实例具有相同的键值

  17. 17

    Hibernate在另一个实体列表中不包括与实体类型相同的子实体

  18. 18

    无法加载,因为已经加载了另一个具有相同文件的 AssetBundle

  19. 19

    如何编写一种方法,该方法接受类型为x的数组以及与该数组具有相同类型的另一个变量

  20. 20

    将一个结构复制到另一个具有相同成员和不同类型的结构

  21. 21

    如何将键值对引用从一个映射复制到另一个相同类型的映射?

  22. 22

    一个实体引用 2 个相同实体类型的实体关系?

  23. 23

    查询以过滤具有相同非主键值的行,然后从 Oracle 中的结果中排除具有另一个空列的记录

  24. 24

    从相同类型的另一个对象更新Entity Framework对象

  25. 25

    ASP.NET MVC链接到相同类型的另一个对象

  26. 26

    从相同类型的另一个对象更新Entity Framework对象

  27. 27

    ASP.NET MVC链接到相同类型的另一个对象

  28. 28

    声明与另一个信号相同类型的信号 (VHDL)

  29. 29

    使用 by 委托给相同类型的另一个对象甚至不编译

热门标签

归档