您非常混淆sql server 中的内容 和上下文缓存中的内容。 DbContext 缓存实体并跟踪它们,因此它知道在调用SaveChanges() 时要做什么。如果实体在缓存中不存在,则由开发人员帮助实体框架确定正确的逻辑。
DbSet.Update(TEntity) Method
开始跟踪处于修改状态的给定实体,以便在调用 SaveChanges() 时在数据库中更新它。
DbSet.Attach(TEntity) Method
开始跟踪处于未更改状态的给定实体,以便在调用 SaveChanges() 时不会执行任何操作。
说到你的意思:
但我更改 Age 属性的方式与 Update() 方法中的相同
是的,你做了,但这不会改变你连接它的方式。事件的顺序非常重要。在以下示例中,我们将 Age 更改为 31 之前,我们将实体附加到实体框架上下文。它不知道您更改了它在更改发生时没有跟踪它(记录不会更改为 31):
using (var context = new EntityContext())
{
p.Age = 31;
context.Persons.Attach(p);
context.SaveChanges();
}
如果 Attach() 无法识别修改的属性,为什么它仍然会生成正确的更新 sql 语句到数据库
如果我们更改事件的顺序以附加实体在我们更改值之前,那么实体框架可以检测到更改并将其保存到数据库(记录将更改为 32): p>
using (var context = new EntityContext())
{
context.Persons.Attach(p);
p.Age = 32;
context.SaveChanges();
}
所有工作示例:
DotNetFiddle Core Example
// Entity Framework Extensions
// Doc: https://entityframework-extensions.net/context-factory
// @nuget: Microsoft.EntityFrameworkCore
// nuget: Z.EntityFramework.Extensions.EFCore
// @nuget: Microsoft.EntityFrameworkCore.SqlServer
// @nuget: Microsoft.Extensions.Logging
using System;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.Extensions.Logging;
using System.Linq;
public class Program
{
public static void Main()
{
var p = new Person();
using (var context = new EntityContext())
{
context.Database.EnsureCreated();
p.Age = 29;
context.Persons.Add(p);
context.SaveChanges();
}
using (var context = new EntityContext())
{
Console.WriteLine("Created Person Age 29");
FiddleHelper.WriteTable("Student", context.Persons.ToList());
}
using (var context = new EntityContext())
{
p.Age = 30;
context.Persons.Update(p);
context.SaveChanges();
}
using (var context = new EntityContext())
{
Console.WriteLine("Update Person Age 30");
FiddleHelper.WriteTable("Student", context.Persons.ToList());
}
using (var context = new EntityContext())
{
p.Age = 31;
context.Persons.Attach(p);
context.SaveChanges();
}
using (var context = new EntityContext())
{
Console.WriteLine("Change Person to 31, THEN Attach");
FiddleHelper.WriteTable("Student", context.Persons.ToList());
}
using (var context = new EntityContext())
{
context.Persons.Attach(p);
p.Age = 32;
context.SaveChanges();
}
using (var context = new EntityContext())
{
Console.WriteLine("Attach THEN Change Person to 32");
FiddleHelper.WriteTable("Student", context.Persons.ToList());
}
}
public class EntityContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connectionString = FiddleHelper.GetConnectionStringSqlServer();
optionsBuilder.UseSqlServer(connectionString);
}
public DbSet<Person> Persons { get; set; }
}
public class Person
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public int Age { get; set; }
public string Name { get; set; }
}
}