对于实体框架来说,具有相同键的两个不同对象不起作用

2024-01-11

我试图在我的主对象中插入对象引用,但如果我不使用其以前管理的对象,EntityFramework 会抱怨。我只是想在创建对象时避免对 dbContext 的依赖。

简化示例:

class Movie {
    public ApplicationUser Owner { get;set; }
}

var myMovie = db.Movies.FirstOrDefault(m, m => m.Id = 1);
myMovie.Owner = new ApplicationUser { Id = 2 };

// I have to attach or change its state, otherwise, EF will complain the object is not complete
db.Entry(myMovie.Owner).State = EntityState.Unchanged;

不知何故,如果上下文之前已加载相同的 ApplicationUser,我会收到此错误:

保存或接受更改失败,因为多个“ApplicationUser”类型的实体具有相同的主键值。确保显式设置的主键值是唯一的。确保在数据库和实体框架模型中正确配置数据库生成的主键。使用实体设计器进行数据库优先/模型优先配置。使用“HasDatabaseGenerateOption”流畅 API 或“DatabaseGenerateAttribute”进行 Code First 配置。

我怎样才能避免这个问题?最好,我不想告诉这个新对象的状态。


如果您有一个仅读取数据而不修改数据的实例,您可以使用AsNoTracking()这将防止您的上下文知道模型的附加实例(它本质上是只读的)。

即使以下代码已检索同一个对象两次,它也应该可以工作。

var myMovieReadOnly = db.Movies.AsNoTracking().FirstOrDefault(m, m => m.Id = 1);

var myMovie = db.Movies.FirstOrDefault(m, m => m.Id = 1);
myMovie.Owner = new ApplicationUser { Id = 2 };

db.SaveChanges();

另一个注意事项是,在仅读取数据的情况下,AsNoTraking() 还可以节省性能。


编辑:刚刚重读并意识到它是 ApplicationUser 模型而不是电影,但相同的概念应该适用于第一个实例的检索。


Edit2:

根据我们的评论,如果您已经知道 ID,您还可以执行以下操作,从而完全不需要进行查找:

class Movie {
    public int OwnerId { get;set; }
    public ApplicationUser Owner { get;set; }
}

var myMovie = db.Movies.FirstOrDefault(m, m => m.Id = 1);
myMovie.OwnerId = 2;
db.SaveChanges();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对于实体框架来说,具有相同键的两个不同对象不起作用 的相关文章

随机推荐