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

奥古兹

当我尝试更新数据库中的条目时引发了异常。首先,我从数据库获取条目以检索条目的记录日期。然后,我将dbmodel迁移到数据模型,然后再迁移回去。但这没有用。

Attaching an entity of type 'ProgramLanguage' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

这是我的dbmodel

public partial class ProgramLanguage
    {
        public int ProgramLanguageId { get; set; }
        public int TestId { get; set; }
        public string ProgramLanguageName { get; set; }
        public string ProgramLanguageLevel { get; set; }
        public Nullable<System.DateTime> RecordDate { get; set; }
    
        public virtual Test Test { get; set; }
    }

这是我的数据模型

[DataContract]
    [Serializable]
    public class ProgramLanguage
    {
        public ProgramLanguage()
        {
            Test = new Test();
        }

        [DataMember]
        public int ProgramLanguageId { get; set; }

        [DataMember]
        public int TestId { get; set; }

        [DataMember]
        public string ProgramLanguageName { get; set; }

        [DataMember]
        public string ProgramLanguageLevel { get; set; }

        [DataMember]
        public DateTime RecordDate { get; set; }

        [DataMember]

        public  Test Test { get; set; }

    }

这是与数据库上下文交互的代码部分。

public bool UpdateProgramLanguage(ProgramLanguage programLanguage)
{
     _repository.Update(programLanguage);
     return true;
}

这是与db模块对话的业务层。

public bool UpdateProgramLanguage(ProgramLanguageDm programLanguage)
        {
            using (var iUnitOfWork = new UnitOfWork<TourismEntities>())
            {
                var coreProgramLanguage = iUnitOfWork.CommonHandler.GetProgramLanguageById(programLanguage.ProgramLanguageId);
                if (coreProgramLanguage == null)
                {
                    return false;
                }
                var detachedCore = GeneralMigrate.ProgramLanguageDmToEntity(GeneralMigrate.ProgramLanguageEntityToDm(coreProgramLanguage));
                var newCore = GeneralMigrate.ProgramLanguageDmToEntity(programLanguage);

                newCore.RecordDate = detachedCore.RecordDate;
                newCore.TestId = detachedCore.TestId;

                return iUnitOfWork.CommonHandler.UpdateProgramLanguage(newCore);
            }
        }

当我将模型迁移到数据模型时,这是代码的一部分。

public static ProgramLanguageDm ProgramLanguageEntityToDm(ProgramLanguage entity)
        {
            return entity != null ? new ProgramLanguageDm{
                TestId = entity.TestId,
                ProgramLanguageId = entity.ProgramLanguageId,
                ProgramLanguageLevel = entity.ProgramLanguageLevel,
                ProgramLanguageName = entity.ProgramLanguageName,
                RecordDate = entity.RecordDate ?? new DateTime(),
            }
            : new ProgramLanguageDm();
        }

        public static ProgramLanguage ProgramLanguageDmToEntity(ProgramLanguageDm dm)
        {
            return dm != null ? new ProgramLanguage {
                TestId = dm.TestId,
                ProgramLanguageId = dm.ProgramLanguageId,
                ProgramLanguageLevel = dm.ProgramLanguageLevel,
                ProgramLanguageName = dm.ProgramLanguageName
            }
            : new ProgramLanguage();
        }
PiGi78

之所以出现此错误,是因为当上下文已经知道具有相同ID的实体时,您试图将对象附加/添加到数据库上下文。

让我做一个简单的例子,以更简单的方式解释它。

我们有这些模型和dto:

public class MyModel
{

    [Key]
    public int Id { get; set; }


    [StringLength(30)]
    public string Description { get; set; }
}


public class MyDTO
{

    public int Id { get; set; }


    public string Description { get; set; }
}

属性不多:Id(主键)和描述。

现在,我用您的代码执行您的操作:

        using (var db = new MyDbContext())
        {

            // In the DB context, there is 1 object with id 1
            var model = await db.MyModels.SingleOrDefaultAsync(x => x.Id == 1);

            // Convert model into DTO
            var dto = new MyDTO { Id = model.Id, Description = model.Description };

            // Convert back to a new model (you do that in your code)
            var anotherModel = new MyModel { Id = dto.Id, Description = dto.Description };


            // Trying to add the model to the db context...
            // It will throw an exception since the db context already has an object with Id = 1 (model)
            // The exception is the same you posted
            db.MyModels.Attach(anotherModel);
        }

查看所有步骤:

  1. 我们从数据库中读取数据(SingleOrDefault)。实体框架为我们提供了一个对象(模型),并将该对象的数据保存在其内存中
  2. 我们将模型转换为DTO(变量称为dto)
  3. 我们将DTO转换回模型。但是我们创建了一个新的模型实例(变量anotherModel)
  4. 我们尝试将新模型添加到Db上下文中。

当我们执行第4步时,应用程序将引发异常,因为DbContext已经知道一个ID = 1的模型(可变模型),并且您不能添加另一个具有相同ID的模型(anotherModel)。

有两种选择:

  1. 当我们读取数据时,可以使用sintax db.MyModels.AsNoTracking()。SingleOrDefault ...代替db.MyModels.SingleOrDefault ...通过“ AsNoTracking”,我们要对db上下文说不要将模型保存在其内存中(跟踪)
  2. 当我们将对象从DTO返回到模型时,我们必须更改原始模型(变量模型),而不是创建一个新模型(另一个模型)。这样做,数据库上下文将看到我们的更改并将其复制到数据库中

查看您的代码,我建议使用第一个选项。这将变得更加容易,并且由于无需进行跟踪,因此查询会更快。

我希望我能帮助

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

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

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档