[英]Two different objects with same key for entity framework does not work
I am trying to insert object reference in my main object but EntityFramework will complain if I don't use its previously managed object. 我试图在我的主对象中插入对象引用,但如果我不使用以前的托管对象,EntityFramework会抱怨。 I simply want to avoid having a dependency on the dbContext when creating my object.
我只是想避免在创建对象时依赖dbContext。
Simplified example: 简化示例:
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;
Somehow, if the same ApplicationUser has been previously loaded by the context, I get this error: 不知何故,如果上次加载了相同的ApplicationUser,我会收到此错误:
Saving or accepting changes failed because more than one entity of type 'ApplicationUser' have the same primary key value.
保存或接受更改失败,因为“ApplicationUser”类型的多个实体具有相同的主键值。 Ensure that explicitly set primary key values are unique.
确保显式设置的主键值是唯一的。 Ensure that database-generated primary keys are configured correctly in the database and in the Entity Framework model.
确保在数据库和Entity Framework模型中正确配置了数据库生成的主键。 Use the Entity Designer for Database First/Model First configuration.
使用实体设计器进行数据库优先/模型优先配置。 Use the 'HasDatabaseGeneratedOption" fluent API or 'DatabaseGeneratedAttribute' for Code First configuration.
使用'HasDatabaseGeneratedOption'流畅API或'DatabaseGeneratedAttribute'进行Code First配置。
How can I avoid this problem? 我该如何避免这个问题? Optimally, I would like to not have to tell the state of that new object.
最理想的是,我不想告诉那个新对象的状态。
If you have an instance where you are only reading data and not modifying it you can use AsNoTracking()
this will prevent having an attached instance of the model that your context knows about (it is essentially read only). 如果你有一个实例,你只读取数据而不修改它,你可以使用
AsNoTracking()
这将阻止你的上下文知道的模型的附加实例(它本质上是只读的)。
The following code should work even though it has retreived the same object twice. 以下代码应该可以工作,即使它已经两次检索同一个对象。
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();
Another note is that AsNoTraking() can also save on performance in scenarios where you are only reading data. 另一个注意事项是,AsNoTraking()还可以在您只读取数据的情况下节省性能。
Edit: Just reread and realized it is the ApplicationUser model and not the movie, but the same concept should apply with retreival of the first instance. 编辑:重新阅读并意识到它是ApplicationUser模型而不是电影,但同样的概念应该适用于第一个实例的retreival。
Edit2: EDIT2:
From our comments you could also do the following the prevent needing to do the lookup at all if you already know the ID: 根据我们的评论,您还可以执行以下操作,如果您已经知道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();
if the same ApplicationUser has been previously loaded by the context, I get this error
如果上次加载了相同的ApplicationUser,我会收到此错误
So first check if the ApplicationUser
is loaded. 因此,首先检查
ApplicationUser
是否已加载。
var newId = 2;
var newApplicationUser = db.ApplicationUsers.Local.FirstOrdefault(u => u.Id == newId)
?? new ApplicationUser { Id = newId };
myMovie.Owner = newApplicationUser;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.