修改后的本地 EF Core 实体仍由新查询获取
Modified local EF Core Entity still fetched by a new query
让我们考虑这两个实体 类:
public class Student
{
public int Id { get; set; }
public int? TeacherId { get; set; }
public virtual Teacher { get; set; }
}
public class Teacher
{
public int Id { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
让我们考虑这个 Entity Framework Core
场景:
var studentSet = dbContext.Set<Student>();
// Get a student
var specialStudent = await studentSet.FindAsync(42);
// Exclude it from the relationship
specialStudent.TeacherId = null;
// Get all the remaining student in the relation ship
var assignedStudents = await studentSet.Where(s => s.TeacherId != null).ToListAsync();
// Do some modifications on assigned students
// Only at the very end of the scenario: commit all the changes to the database in one call
await dbContext.SaveChangesAsync();
我的问题是我的 specialStudent
是 assignedStudents
的一部分,即使它的 TeacherId
正如预期的那样为空。
我猜 Entity Framework Core 会 运行 查询数据库,将结果与其缓存的实体进行比较,获取丢失的实体,然后重新 运行查询以从结果中排除不适合查询的已修改实体。
我想我最后的猜测是错误的。
是否可以达到我想要的效果?
我不知道它是否与我在 3.1.4
版本中使用 Npgsql.EntityFrameworkCore.PostgreSQL
相关,并且我的 DbContext 配置为使用代理 (optionsBuilder.UseLazyLoadingProxies()
)。
在其他情况下,为了使用您的算法,您使用了事务(仅当您需要将 TeacherId 分配给 null 并同时修改其他学生时)并在每个步骤后调用 SaveChanges。此外,您必须标记 EntityState.Modified 每条修改记录(或 属性),否则将不会保存到数据库。
为什么不用这个?
var assignedStudents = await dbContext.Students.Where(s => s.Id !=42 ) .ToListAsync();
// Do some modifications on assigned students
var specialStudent = await dbContext.Students.Where(s => s.Id ==42 )
specialStudent.TeacherId = null;
dbContext.Entry(specialStudent).State = EntityState.Modified;
await dbContext.SaveChangesAsync()
我不明白为什么 Panagiotis Kanavos 在评论中说我不应该这样做。交易就是为了这个目的而存在的,Entity Framework 让我们可以很容易地使用它。我不明白为什么会 break EF's way of working
.
这就是为什么我不会立即将其标记为已接受的答案,因此 he/someone else 可以解释为什么它不好。但与此同时,这对我有用:
// Initialize the transaction
await dDbContext.Database.BeginTransactionAsync();
var studentSet = dbContext.Set<Student>();
// Get a student
var specialStudent = await studentSet.FindAsync(42);
// Exclude it from the relationship
specialStudent.TeacherId = null;
// Apply the changes locally so it can be reflected in the next calls
// Since there is a transaction "in progress", the changes are not commited to the database
await dbContext.SaveChangesAsync();
// Get all the remaining student in the relationship
// This time, mySpecialStudent is no longer part of the results
var assignedStudents = await studentSet.Where(s => s.TeacherId != null).ToListAsync();
// Do some modifications on assigned students
// Save the changes to thoses entities
await dbContext.SaveChangesAsync();
// Only at the very end of the scenario commit the transaction to push the data to the database
await dbContext.Database.CurrentTransaction.CommitAsync();
让我们考虑这两个实体 类:
public class Student
{
public int Id { get; set; }
public int? TeacherId { get; set; }
public virtual Teacher { get; set; }
}
public class Teacher
{
public int Id { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
让我们考虑这个 Entity Framework Core
场景:
var studentSet = dbContext.Set<Student>();
// Get a student
var specialStudent = await studentSet.FindAsync(42);
// Exclude it from the relationship
specialStudent.TeacherId = null;
// Get all the remaining student in the relation ship
var assignedStudents = await studentSet.Where(s => s.TeacherId != null).ToListAsync();
// Do some modifications on assigned students
// Only at the very end of the scenario: commit all the changes to the database in one call
await dbContext.SaveChangesAsync();
我的问题是我的 specialStudent
是 assignedStudents
的一部分,即使它的 TeacherId
正如预期的那样为空。
我猜 Entity Framework Core 会 运行 查询数据库,将结果与其缓存的实体进行比较,获取丢失的实体,然后重新 运行查询以从结果中排除不适合查询的已修改实体。
我想我最后的猜测是错误的。
是否可以达到我想要的效果?
我不知道它是否与我在 3.1.4
版本中使用 Npgsql.EntityFrameworkCore.PostgreSQL
相关,并且我的 DbContext 配置为使用代理 (optionsBuilder.UseLazyLoadingProxies()
)。
在其他情况下,为了使用您的算法,您使用了事务(仅当您需要将 TeacherId 分配给 null 并同时修改其他学生时)并在每个步骤后调用 SaveChanges。此外,您必须标记 EntityState.Modified 每条修改记录(或 属性),否则将不会保存到数据库。
为什么不用这个?
var assignedStudents = await dbContext.Students.Where(s => s.Id !=42 ) .ToListAsync();
// Do some modifications on assigned students
var specialStudent = await dbContext.Students.Where(s => s.Id ==42 )
specialStudent.TeacherId = null;
dbContext.Entry(specialStudent).State = EntityState.Modified;
await dbContext.SaveChangesAsync()
我不明白为什么 Panagiotis Kanavos 在评论中说我不应该这样做。交易就是为了这个目的而存在的,Entity Framework 让我们可以很容易地使用它。我不明白为什么会 break EF's way of working
.
这就是为什么我不会立即将其标记为已接受的答案,因此 he/someone else 可以解释为什么它不好。但与此同时,这对我有用:
// Initialize the transaction
await dDbContext.Database.BeginTransactionAsync();
var studentSet = dbContext.Set<Student>();
// Get a student
var specialStudent = await studentSet.FindAsync(42);
// Exclude it from the relationship
specialStudent.TeacherId = null;
// Apply the changes locally so it can be reflected in the next calls
// Since there is a transaction "in progress", the changes are not commited to the database
await dbContext.SaveChangesAsync();
// Get all the remaining student in the relationship
// This time, mySpecialStudent is no longer part of the results
var assignedStudents = await studentSet.Where(s => s.TeacherId != null).ToListAsync();
// Do some modifications on assigned students
// Save the changes to thoses entities
await dbContext.SaveChangesAsync();
// Only at the very end of the scenario commit the transaction to push the data to the database
await dbContext.Database.CurrentTransaction.CommitAsync();