Sha*_*ant 90 c# entity-framework
让我们说我查询数据库并加载项目列表.然后我打开详细视图表单中的一个项目,而不是从数据库中重新查询该项目,我从列表中的数据源创建项目的实例.
有没有办法可以更新数据库记录而无需获取单个项目的记录?
以下是我现在正在做的一个示例:
dataItem itemToUpdate = (from t in dataEntity.items
where t.id == id
select t).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
然后在拉动记录后,我更新项目中的一些值并将记录推回:
itemToUpdate.itemstatus = newStatus;
dataEntity.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
我认为有更好的方法可以做到这一点,任何想法?
CD.*_*D.. 66
您应该使用Attach()方法.
Ami*_*adi 53
ExecuteUpdate
:最后!经过漫长的等待,EF Core 7.0 现在拥有原生支持的运行UPDATE
(以及DELETE
)语句的方式,同时还允许您使用任意 LINQ 查询 ( .Where(u => ...)
),而无需先从数据库中检索相关实体:新的内置ExecuteUpdate
名为\xe2\x80\x94的方法请参阅“EF Core 7.0 中有哪些新增功能?” 和官方文档。
ExecuteUpdate
正是针对此类场景,它可以在任何IQueryable
实例上操作,并允许您更新任意数量的行上的特定列,同时始终在幕后发出单个语句 UPDATE
,使其尽可能高效。
想象一下您想要更新Email
特定用户的列:
dbContext.Users\n .Where(u => u.Id == someId)\n .ExecuteUpdate(b =>\n b.SetProperty(u => u.Email, "NewEmail@gmail.com")\n );\n
Run Code Online (Sandbox Code Playgroud)\n正如您所看到的,调用ExecuteUpdate
需要您调用该SetProperty
方法,指定要更新哪个属性,以及要为其分配什么新值。
EF Core 会将其转换为以下UPDATE
语句:
UPDATE [u]\n SET [u].[Email] = "NewEmail@gmail.com"\nFROM [Users] AS [u]\nWHERE [u].[Id] = someId\n
Run Code Online (Sandbox Code Playgroud)\nExecuteDelete
对于删除行:还有一个与ExecuteUpdate
calledExecuteDelete
相对应的功能,顾名思义,它可以用于一次删除单行或多行,而无需先获取它们。
// Delete all users that haven\'t been active in 2022:\ndbContext.Users\n .Where(u => u.LastActiveAt.Year < 2022)\n .ExecuteDelete();\n
Run Code Online (Sandbox Code Playgroud)\n与 类似ExecuteUpdate
,会在后台ExecuteDelete
生成SQL 语句 \xe2\x80\x94 在本例中,如下所示:DELETE
DELETE FROM [u]\nFROM [Users] AS [u]\nWHERE DATEPART(year, [u].[LastActiveAt]) < 2022\n
Run Code Online (Sandbox Code Playgroud)\n其他注意事项:
\nExecuteUpdate
都是ExecuteDelete
“终止”的,这意味着一旦您调用该方法,更新/删除操作就会发生。你不应该dbContext.SaveChanges()
事后打电话。SetProperty
,并且对为什么ExectueUpdate
不接收成员初始化表达式感到困惑(例如.ExecuteUpdate(new User { Email = "..." })
,请参阅此评论此功能的 GitHub 问题上的(以及周围的评论) 。Execute
此外,如果您对命名背后的基本原理以及为什么选择前缀(还有其他候选者)感到好奇,请参阅此评论以及前面的(相当长的)对话。async
等效的方法,分别名为ExecuteUpdateAsync
、 和ExecuteDeleteAsync
。bar*_*ker 36
您还可以使用数据存储区的上下文对数据库使用直接SQL.例:
dataEntity.ExecuteStoreCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = 123 ");
Run Code Online (Sandbox Code Playgroud)
出于性能原因,您可能希望传入变量而不是单个硬编码的SQL字符串.这将允许SQL Server缓存查询并使用参数重用.例:
dataEntity.ExecuteStoreCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
Run Code Online (Sandbox Code Playgroud)
更新 - 适用于EF 6.0
dataEntity.Database.ExecuteSqlCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
Run Code Online (Sandbox Code Playgroud)
tec*_*cla 13
代码:
ExampleEntity exampleEntity = dbcontext.ExampleEntities.Attach(new ExampleEntity { Id = 1 });
exampleEntity.ExampleProperty = "abc";
dbcontext.Entry<ExampleEntity>(exampleEntity).Property(ee => ee.ExampleProperty).IsModified = true;
dbcontext.Configuration.ValidateOnSaveEnabled = false;
dbcontext.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
结果TSQL:
exec sp_executesql N'UPDATE [dbo].[ExampleEntities]
SET [ExampleProperty ] = @0
WHERE ([Id] = @1)
',N'@0 nvarchar(32),@1 bigint',@0='abc',@1=1
Run Code Online (Sandbox Code Playgroud)
注意:
需要"IsModified = true"行,因为在创建新的ExampleEntity对象时(仅填充了Id属性),所有其他属性都具有其默认值(0,null等).如果要使用"默认值"更新数据库,实体框架将不会检测到更改,然后不会更新数据库.
例如:
exampleEntity.ExampleProperty = null;
Run Code Online (Sandbox Code Playgroud)
如果没有"IsModified = true"这一行将无法工作,因为属性ExampleProperty在创建空的ExampleEntity对象时已经为空,您需要向EF说这个列必须更新,这就是这一行的目的.
如果DataItem
有字段EF将预先验证(如非可空字段),我们将不得不为此上下文禁用该验证:
DataItem itemToUpdate = new DataItem { Id = id, Itemstatus = newStatus };
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.Configuration.ValidateOnSaveEnabled = false;
dataEntity.SaveChanges();
//dataEntity.Configuration.ValidateOnSaveEnabled = true;
Run Code Online (Sandbox Code Playgroud)
否则,我们可以尝试满足预验证,仍然只更新单列:
DataItem itemToUpdate = new DataItem
{
Id = id,
Itemstatus = newStatus,
NonNullableColumn = "this value is disregarded - the db original will remain"
};
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
假设dataEntity
是System.Data.Entity.DbContext
您可以通过将此添加到以下内容来验证生成的查询DbContext
:
/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m);
Run Code Online (Sandbox Code Playgroud)
如果您需要使用相同表达式更新数百或数千个实体,则使用 Entity Framework Core 进行更新可能会非常慢。实体在更新之前首先加载到上下文中,这对性能非常不利,然后它们被一个接一个地更新,这使得更新操作变得更糟。
EF+ 批量更新在单个数据库往返中使用表达式更新多行,并且无需在上下文中加载实体。
// using Z.EntityFramework.Plus; // Don't forget to include this.
// UPDATE all users inactive for 2 years
var date = DateTime.Now.AddYears(-2);
ctx.Users.Where(x => x.LastLoginDate < date)
.Update(x => new User() { IsSoftDeleted = 1 });
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
60256 次 |
最近记录: |