.NET Core 更新部分字段方法总结


一、利用TryUpdateModelAsync

        此方法首先查询出实体数据,然后根据lambda表达式中的字段进行更新对应的实体字段,注意lambda表达式,都为这样的参数格式o=>o.x1,o=>o.x2而不是o=>o.x1,o.x2

        [ValidateAntiForgeryToken]

        public async Task<ActionResult> EditAsync(int? id)         {              if (id ==null)             {                 return NotFound();             }             if (ModelState.IsValid)             {                 try                 {                     var q = dbContext.LeaveRecord.Find(id);                     if (await TryUpdateModelAsync(q, "", o => o.PersonName, o => o.LeaveType,  o => o.Sex))                     {                         await dbContext.SaveChangesAsync();                     }                 }                 catch                 {                     return View();                 }                 return RedirectToAction(nameof(Index));             }             return View();         }

二、查询出实体,然后将表单form中的实体字段值赋给查询出来的实体对应字段

        [ValidateAntiForgeryToken]
        public ActionResult EditAsync(int? id, LeaveRecord leaveRecord)
        { 
            if (id ==null)
            {
                return NotFound();
            }
            if (ModelState.IsValid)
            {
                try
                {
                    var q = dbContext.LeaveRecord.Find(id);
                    q.PersonName = leaveRecord.PersonName;
                    q.Sex = leaveRecord.Sex;
                    q.LeaveType = leaveRecord.LeaveType;
                    q.LeaveReason = leaveRecord.LeaveReason;
 
                    dbContext.Update(q);
                    dbContext.SaveChanges();
                }
                catch
                {
                    return View();
                }
                return RedirectToAction(nameof(Index));
            }
            return View();
        }

三、字段绑定更新部分,将所有字段值读出来,然后在html中将不更新的字段设置为readonly,这样用户只能操作需要更新的字段值,但这也有一个问题,如果用户懂计算机,将实体在html中的readonly去掉,会导致后台更新数据 的同时会把值更新

<input type="text" readonly asp-for="Title" />

<input type="text" asp-for="Content" />

四、利用属性设置更新部分字段,适用于更新字段少的情况,比如实体总共有10个字段,仅更新两个或一个字段的情况下,可以设置如下 :比如只更新了username字段

     public ActionResult Edit(int id, User user)
        {
            try
            {
                dbContext.Attach(user);
                //将需要更新的字段设置为true,没有设置的字段不更新,这种方法不用查询数据库找到实体
                dbContext.Entry(user).Property(o => o.UserName).IsModified = true;
 
                dbContext.SaveChanges();
 
                return RedirectToAction(nameof(Index));
            }
            catch(Exception ex)
            {
                return View();
            }
        }

当然这样的语句可以用循环的方式实现,将需要更新的字段封装起来,然后通过循环遍历设置为true,以下代码可以参考

public void UpdateEntityFields(T entity, List<string> fileds)

{             if (entity != null&&fileds!=null)             {                 dbContext.CreateObjectSet<T>().Attach(entity);                 var SetEntry = ((IObjectContextAdapter)dbContext).ObjectContext.                     ObjectStateManager.GetObjectStateEntry(entity);                 foreach (var t in fileds)                 {                     SetEntry.SetModifiedProperty(t);                 }             } }

五、如果更新字段较多,上面的方法都要写一堆需要更新字段的代码,假如有10个字段,更新9个,仅有一个字段不更新,那么,可以用以下方法,此方法适用总字段较多,但更新的字段较少的情况,和上面的正好相反。

dbContext.Entry(user).State = EntityState.Modified;//将所有字段设置为要更新的状态

dbContext.Entry(user).Property(o=>o.UserName).IsModified = false;//再将不需要的字段设置为不更新,那么这样就达到了更新多个字段,除此字段外    注意:第四、五方法中用了Attach,所以在SaveChanges()前面一定不要再加dbContext.Update(user);加上此句会出错,导致上面的设置状态无效,会全部更新,所以一定不要加。  

六、使用原生SQL执行更新操作

dbContext.Database.ExecuteSqlRaw("sql语句",参数1值, 参数2值,...);

 public ActionResult Edit(int id, User user)
 {
   try
   {
         dbContext.Database.ExecuteSqlRaw($"update User set userName='{user.UserName}',userpassword='{user.UserPassword}' where id={user.Id}");
         return RedirectToAction(nameof(Index));
    }
    catch (Exception ex)
    {
        return View();
    }
}

向原始 SQL 查询引入任何用户提供的值时,必须注意防范 SQL 注入攻击。 除了验证确保此类值不包含无效字符,请始终使用会将值与 SQL 文本分开发送的参数化处理。

具体而言,如果连接和内插的字符串 ($"") 带有用户提供的未经验证的值,则切勿将其传递到 FromSqlRaw 或 ExecuteSqlRaw

通过 FromSqlInterpolated 和 ExecuteSqlInterpolated 方法,可采用一种能抵御 SQL 注入攻击的方式使用字符串内插语法。一般这种方法用于内部确定的更新操作。比如将某个字段更新为某个值等。

以上方法必须保证参数值是经过处理的,否则不建议用$""这样的形式。下面的两个方法进行参数化防止sql注入攻击:

  • 第一种简写:  
dbContext.Database.ExecuteSqlRaw("update User set userName={0},userpassword={1} where id={2}","user01","123123",3);//将id=3的user用户名和密码进行更新 
  • 第二种参数写法:参数化赋值 

        mysql用 MySqlParameter,sql用SqlParameter,注意对应关系否则出错,代码如下: 

int id=3;
dbContext.Database.ExecuteSqlRaw(
    "update User set userName=@userName,userpassword=@password where id=@id", new SqlParameter("@userName", "jone"), new SqlParameter("@password", "12345"), new SqlParameter("@id",id)
);

  上述几种方法根据具体情况使用即可。