如何在Razor Pages中执行带多条件WHERE子句的原生SQL更新?
没问题,我分两部分来帮你解决这两个需求:
一、实现多条件的EF Core更新语句
你现在用_context.SaveChanges()默认是按实体主键生成WHERE条件,要添加多条件的话,有两种常用方式:
方法1:查询符合条件的实体后修改(适合数据量小的场景)
先通过Where筛选出满足StaffID + EmpID + StaffAssetName条件的记录,修改字段后再保存。这种方式直观,适合少量数据:
// 你的Razor Page后端代码(比如XXX.cshtml.cs) public async Task<IActionResult> OnPostUpdateAssetsAsync() { // 假设你从前端接收了这些参数(可通过绑定属性获取) int targetStaffId = 123; int targetEmpId = 456; string targetAssetName = "Laptop"; // 新的字段值 int newEmpId = 789; DateTime newIssuedDate = DateTime.Now; // 其他字段同理... // 筛选出要更新的实体 var assets = await _context.StaffAssets .Where(s => s.StaffID == targetStaffId && s.EmpID == targetEmpId && s.StaffAssetName == targetAssetName) .ToListAsync(); // 批量修改字段 foreach (var asset in assets) { asset.EmpID = newEmpId; asset.IssuedDate = newIssuedDate; asset.LastModifiedBy = User.Identity?.Name ?? "System"; asset.LastModifiedTimestamp = DateTime.Now; // 设置其他需要更新的字段 } // 保存更改,此时生成的SQL会包含你要的三个WHERE条件 await _context.SaveChangesAsync(); return RedirectToPage("./AssetsList"); }
方法2:用ExecuteUpdate批量更新(EF Core 7+推荐,效率更高)
如果你的项目用的是EF Core 7或更高版本,推荐用ExecuteUpdate方法——它不需要先加载实体到内存,直接生成你需要的多条件UPDATE语句,性能更好:
public async Task<IActionResult> OnPostBulkUpdateAsync() { int targetStaffId = 123; int targetEmpId = 456; string targetAssetName = "Laptop"; // 新字段值 int newEmpId = 789; DateTime newIssuedDate = DateTime.Now; // 执行批量更新,直接生成带多条件的SQL int affectedRows = await _context.StaffAssets .Where(s => s.StaffID == targetStaffId && s.EmpID == targetEmpId && s.StaffAssetName == targetAssetName) .ExecuteUpdateAsync(setters => setters .SetProperty(a => a.EmpID, newEmpId) .SetProperty(a => a.IssuedDate, newIssuedDate) .SetProperty(a => a.LastModifiedBy, User.Identity?.Name ?? "System") .SetProperty(a => a.LastModifiedTimestamp, DateTime.Now) // 继续添加其他需要更新的字段 ); // affectedRows会返回被修改的行数,可用于验证更新是否生效 return RedirectToPage("./AssetsList"); }
二、在Razor Pages中执行原生SQL
如果需要直接执行原生SQL,EF Core提供了对应的方法,注意一定要用参数化方式防止SQL注入:
1. 执行原生更新SQL
用Database.ExecuteSqlInterpolatedAsync(推荐,自动参数化)或者ExecuteSqlRawAsync:
public async Task<IActionResult> OnPostRawUpdateAsync() { int targetStaffId = 123; int targetEmpId = 456; string targetAssetName = "Laptop"; int newEmpId = 789; DateTime newIssuedDate = DateTime.Now; string modifiedBy = User.Identity?.Name ?? "System"; // 执行原生更新,插值字符串会自动转为参数,防止注入 int affectedRows = await _context.Database.ExecuteSqlInterpolatedAsync($@" UPDATE [StaffAssets] SET [EmpID] = {newEmpId}, [IssuedDate] = {newIssuedDate}, [LastModifiedBy] = {modifiedBy}, [LastModifiedTimestamp] = {DateTime.Now} -- 添加其他需要更新的字段 WHERE [StaffID] = {targetStaffId} AND [EmpID] = {targetEmpId} AND [StaffAssetName] = {targetAssetName}"); return RedirectToPage("./AssetsList"); }
2. 执行原生查询SQL
用FromSqlInterpolated或FromSqlRaw来执行查询,返回实体:
public async Task<IActionResult> OnGetRawQueryAsync() { int targetStaffId = 123; int targetEmpId = 456; string targetAssetName = "Laptop"; // 执行原生查询,返回StaffAssets实体列表 var assets = await _context.StaffAssets .FromSqlInterpolated($@" SELECT * FROM [StaffAssets] WHERE [StaffID] = {targetStaffId} AND [EmpID] = {targetEmpId} AND [StaffAssetName] = {targetAssetName}") .ToListAsync(); // 将结果赋值给PageModel的属性,供前端页面显示 Assets = assets; return Page(); }
注意事项
- 避免SQL注入:绝对不要直接拼接用户输入到SQL字符串里,使用上述参数化方法(插值字符串、ExecuteUpdate的表达式)
- EF Core版本限制:
ExecuteUpdate是EF Core 7才引入的,如果你的版本低于7,只能用查询实体修改或原生SQL的方式 - DbContext依赖注入:确保你的Razor Page已经通过构造函数注入了DbContext(在Program.cs中配置
builder.Services.AddDbContext<YourDbContext>(...))
内容的提问来源于stack exchange,提问作者Teena
相关产品推荐
相关产品推荐

