【问题标题】:Update records using LINQ使用 LINQ 更新记录
【发布时间】:2021-03-11 08:32:21
【问题描述】:

我需要在表中为行的子集设置一个值。在 SQL 中,我会这样做:

UPDATE dbo.Person SET is_default = 0 WHERE person_id = 5

有没有办法在 LINQ 中做到这一点?

我目前使用的是:

var result = (from p in Context.People....)

符号。

有我可以使用的更新方法吗?还是我必须获取所有记录,然后在 Foreach 中一一更新?

如果可能的话,这是最有效的方法吗?

(from p in Context.person_account_portfolio where p.person_id == personId select p)
   .ToList()
   .ForEach(
       x =>
       x.is_default =
       false);

【问题讨论】:

    标签: c# linq entity-framework


    【解决方案1】:

    这个效果最好。

    (from p in Context.person_account_portfolio 
     where p.person_id == personId select p).ToList()
                                            .ForEach(x => x.is_default = false);
    
    Context.SaveChanges();
    

    【讨论】:

    • 您能解释一下这个查询吗? @克雷格
    • 是的!很有必要!
    • List 和 ForEach 有没有必要这样做?这是不必要的额外计算和内存分配吗?我在问题上发布了一个更有效的示例...
    【解决方案2】:

    我假设person_idPerson 表的主键,所以这是更新单个记录的方法:

    Person result = (from p in Context.Persons
                  where p.person_id == 5
                  select p).SingleOrDefault();
    
    result.is_default = false;
    
    Context.SaveChanges();
    

    以下是更新多条记录的方法:

    List<Person> results = (from p in Context.Persons
                            where .... // add where condition here
                            select p).ToList();
    
    foreach (Person p in results)
    {
        p.is_default = false;
    }
    
    Context.SaveChanges();
    

    【讨论】:

      【解决方案3】:

      作为已接受答案的补充,您可能会发现使用 LINQ 方法语法时您的代码看起来更加一致:

      Context.person_account_portfolio
      .Where(p => person_id == personId)
      .ToList()
      .ForEach(x => x.is_default = false);
      

      .ToList() 是必需的,因为 .ForEach() 仅在 List&lt;T&gt; 上定义,而不是在 IEnumerable&lt;T&gt; 上定义。请注意.ToList() 将在执行循环之前执行查询并从数据库中加载所有匹配的行。

      【讨论】:

      • 最简洁的解决方案。值得注意的是,ToList 将创建 IEnumerable 的副本,并对所有元素运行复制构造函数。我不是在评判,我一直都在使用它,并且非常喜欢 List->ForEach。我只是说如果你有数以百万计的 person_account_portfolio 并且整天都在打这个,那么使用不太漂亮的 IEnumerable->foreach 来代替可能是明智的。
      【解决方案4】:

      据我所知,您有两种选择:

      1. 执行您的查询,对其进行迭代以修改实体,然后调用SaveChanges()
      2. 执行您在问题顶部提到的 SQL 命令。要了解如何执行此操作,请查看 this page

      如果您使用选项 2,您将失去 Entity Framework 为您提供的一些抽象,但如果您需要执行非常大的更新,出于性能原因,这可能是最佳选择。

      【讨论】:

        【解决方案5】:

        是的。您可以使用foreach 来更新linq 中的记录。没有性能下降。

        您可以验证标准Where 运算符是使用C# 2.0 中引入的yield 构造实现的。

        use of yield has an interesting benefit 表示查询是 在迭代之前不会实际评估,或者使用 foreach 语句或手动使用底层 GetEnumerator 和 MoveNext 方法

        例如,

        var query = db.Customers.Where (c => c.Name.StartsWith ("A"));
        query = query.Where (c => c.Purchases.Count() >= 2);
        var result = query.Select (c => c.Name);
        
        foreach (string name in result)   // Only now is the query executed!
           Console.WriteLine (name);
        

        例外运算符有: 首先,ElementAt、Sum、Average、All、Any、ToArray 和 ToList 强制立即进行查询评估。

        所以不必害怕使用foreach 来获取update linq 结果。

        在您的案例中,下面给出的代码示例将有助于更新许多属性,

         var persons = (from p in Context.person_account_portfolio where p.person_name == personName select p);
        
        //TO update using foreach
        
        foreach(var person in persons)
        {
        //update property values
        }  
        

        希望对你有帮助……

        【讨论】:

        • yield 是一个红鲱鱼:这是一个实现细节。
        【解决方案6】:

        是的,您必须获取所有记录,更新它们,然后致电SaveChanges

        【讨论】:

          【解决方案7】:

          奇怪的是,对我来说它是 SubmitChanges 而不是 SaveChanges:

              foreach (var item in w)
              {
                  if (Convert.ToInt32(e.CommandArgument) == item.ID)
                  {
                      item.Sort = 1;
                  }
                  else
                  {
                      item.Sort = null;
                  }
                  db.SubmitChanges();            
              }                   
          

          【讨论】:

          • 在这里阅读:stackoverflow.com/questions/10980619/… 你可能不应该在每次迭代时调用.SubmitChanges()...
          • 如果代码以 Language = C# 语句运行。它不会引起问题,您通常需要在每次执行后重新执行它。
          【解决方案8】:
          public ActionResult OrderDel(int id)
              {
                  string a = Session["UserSession"].ToString();
                  var s = (from test in ob.Order_Details where test.Email_ID_Fk == a && test.Order_ID == id select test).FirstOrDefault();
                  s.Status = "Order Cancel By User";
                  ob.SaveChanges();
                  //foreach(var updter in s)
                  //{
                  //    updter.Status = "Order Cancel By User";
                  //}
          
          
                  return Json("Sucess", JsonRequestBehavior.AllowGet);
              } <script>
                      function Cancel(id) {
                          if (confirm("Are your sure ? Want to Cancel?")) {
                              $.ajax({
          
                                  type: 'POST',
                                  url: '@Url.Action("OrderDel", "Home")/' + id,
                                  datatype: 'JSON',
                                  success: function (Result) {
                                      if (Result == "Sucess")
                                      {
                                          alert("Your Order has been Canceled..");
                                          window.location.reload();
                                      }
                                  },
                                  error: function (Msgerror) {
                                      alert(Msgerror.responseText);
                                  }
          
          
                              })
                          }
                      }
          
                  </script>
          

          【讨论】:

            【解决方案9】:

            作为对上述答案的评论的回应,这是我的解决方案,它使用了没有中断或抽象的 Linq 查询,但它避免了对 List 和 ForEach 不必要地使用内存和计算...

            (from p in Context.person_account_portfolio 
                             where p.personId == personId 
                             select p).FirstOrDefault().is_default .Equals(false);
            

            【讨论】:

            • 这似乎不符合 OP 的要求,您的 '.Equals' 只是返回一个值,而不是更新值。此外,您是否只选择第一个值,但 OP 说可能有多个(如果没有,您将得到空异常)。最初的 sql 表示 Person 表,因此我们可能会猜测 PersonId 是一个 PK,但随后他谈到 person_account_portfolio 并循环,因此在这种情况下,FK 是一个更好的猜测。
            猜你喜欢
            • 2013-12-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-08-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多