1.先查询,再修改
实体是通过上下文获得的,因此上下文立即开始对其进行跟踪。 当您更改跟踪实体的属性值时,上下文会将实体的EntityState更改为Modified,并且ChangeTracker记录旧属性值和新属性值。 调用SaveChanges时,数据库将生成并执行UPDATE语句。如果发现修改值和原始值相同时,State是unchanged
var user = testDbContext.User.Include(a => a.Orders).First(a => a.UserId == 1);
user.FirstName = "zhang";
EntityState ss = testDbContext.Entry(user).State;//unchanged
testDbContext.SaveChanges();
user.FirstName = "zhang1";
EntityState ss1 = testDbContext.Entry(user).State;//modifed
testDbContext.SaveChanges();
var author = context.Authors.First(a => a.AuthorId == 1);
author.FirstName = "Bill";
context.SaveChanges();
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Authors] SET [FirstName] = @p0
WHERE [AuthorId] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000)',@p1=1,@p0=N'Bill'
2.设置 EntityState的状态
public void updateEntityState()
{
User u = new User();
u.FirstName = "zhang";
u.UserId = 1;
testDbContext.Entry(u).State = EntityState.Modified;
testDbContext.SaveChanges();
}
UPDATE[User] SET[DefaultCurrencyCode] = @p0, [FirstName] = @p1, [LastName] = @p2, [SecurityLevel] = @p3
WHERE[UserId] = @p4;
SELECT @@ROWCOUNT;
虽然在代码中定义修改两个属性,但是这种方式依然会把没有定义的属性值设置成null.
3.调用EF CORE 的Update() 方法
public void update()
{
User u = new User();
u.DefaultCurrencyCode = "USD";
u.FirstName = "zhang";
u.LastName = "feng";
u.SecurityLevel = 1;
u.UserId = 1;
testDbContext.Update(u);
EntityState ss = testDbContext.Entry(u).State;
testDbContext.SaveChanges();
}
UPDATE[User] SET[DefaultCurrencyCode] = @p0, [FirstName] = @p1, [LastName] = @p2, [SecurityLevel] = @p3
WHERE[UserId] = @p4;
SELECT @@ROWCOUNT;
此方法与显式设置State属性的区别在于,上下文将以Modified状态开始跟踪任何相关实体,从而为每个实体生成UPDATE语句。 如果关系表未分配键值,并且关系实体类不为空,则将其标记为“added”,并生成INSERT语句。这种方式也是会把没有定义的属性值设置成null(will generate SQL to update all properties)
4.Attach
https://blog.csdn.net/xiaomifengmaidi1/article/details/102809224
在实体上使用Attach方法时,其状态将设置为Unchanged,这将导致根本不生成任何数据库命令。 定义了键值的所有其他关联实体类也将设置为“Unchanged”。 如果关系实体类未分配键值,并且关系实体类不为空,则将其标记为“added”。 可以跟踪任何实体类中的任何属性,设置state 为modified
public void updateAttach()
{
User u = new User();
u.FirstName = "zhang";
u.UserId = 2;
testDbContext.Attach(u);
testDbContext.Entry(u).State = EntityState.Modified;
testDbContext.SaveChanges();
}
UPDATE[User] SET[FirstName] = @p0
WHERE[UserId] = @p1;
SELECT @@ROWCOUNT;
5.TrackGraph
TrackGraph API提供对对象单个实体的访问,并使您能够针对每个实体单独执行自定义代码。 这在处理由不同状态的各种相关实体组成的复杂对象情况下很有用。
public void updateTrack()
{
var u = new User
{
UserId = 1,
FirstName = "William",
LastName = "Shakespeare"
};
u.Orders = new List();
u.Orders.Add(new Order { Address = "test1",OrderId=1002 });
testDbContext.ChangeTracker.TrackGraph(u, e => {
if ((e.Entry.Entity as User) != null)
{
e.Entry.State = EntityState.Unchanged;
}
else
{
e.Entry.State = EntityState.Modified;
}
});
testDbContext.SaveChanges();
}
这这里, testDbContext.ChangeTracker.TrackGraph会循环user下所有的实体类包括自己,所以我们如果不需要update user的话, if ((e.Entry.Entity as User) != null)
{
e.Entry.State = EntityState.Unchanged;
}
写上这句话,当然这种方式实体类的属性也会全部更新的,数据库表中不能存在Timestamp字段,不然可能需要做一些其他的设置,不然更新不成功