簡體   English   中英

C# ASP.Net MVC 更新數據庫中的多行正在創建額外的行

[英]C# ASP.Net MVC Updating Multiple rows in database is creating extra rows

我的數據庫中有一到兩行可以並且將在給定時間根據Id更新。 這是我能夠發送到視圖並將其提交到 controller 中的[HttpPost]方法的數據List<>就好了,但是當我調用我創建的更新方法時,它會找到相應的行和通過foreach循環應該更新它們,但實際上只是將更新的數據作為兩個新行添加到表中。 我似乎無法弄清楚我做錯了什么。

更新前的表格

+------+--------+-------------+------------+-------------+
|  ID  | ItemID | PriceTypeID | ListTypeID | DirectPrice |
+------+--------+-------------+------------+-------------+
| 1021 |  62238 |           2 |          1 |        0.00 |
| 1022 |  62238 |           3 |          1 |        0.00 |
+------+--------+-------------+------------+-------------+

更新 Function

public static void UpdateItem(List<PricingOptionDTO> pricingOptionDTO)      
using (DBContext context = new DBContext()) {

 foreach (var item in pricingOptionDTO)
 {
     Entities.PricingOption pricingOptionTb = context.PricingOptions.Where(a => a.ID.Equals(item.ID)).FirstOrDefault();

        if (pricingOptionTb != null)
           {                                                
            pricingOptionTb .DirectPrice = item.DirectPrice;                
            pricingOptionTb .Increment = item.BidIncrement;
            pricingOptionTb .WarningCap = item.BidWarningCap;
           }

         context.PricingOptions.Add(pricingOptionTb);
         context.SaveChanges(); 
   }
       
      context.SaveChanges(); 
}

更新后的表格

+------+--------+-------------+------------+-------------+
|  ID  | ItemID | PriceTypeID | ListTypeID | DirectPrice |
+------+--------+-------------+------------+-------------+
| 1021 |  62238 |           2 |          1 |        0.00 |
| 1022 |  62238 |           3 |          1 |        0.00 |
| 1023 |  62238 |           2 |          1 |        1.00 |
| 1024 |  62238 |           3 |          1 |        2.00 |
+------+--------+-------------+------------+-------------+

您的示例中缺少某些內容:

context.PricingOptions.Add(PricingOption);

這里的“PricingOption”是什么?

示例中缺少的最明顯的可能解釋您所看到的行為的東西是需要else條件:

 Entities.PricingOption pricingOptionTb = context.PricingOptions.Where(a => a.ID.Equals(item.ID)).SingleOrDefault();

if (pricingOptionTb != null)
{                                                
    pricingOptionTb .DirectPrice = item.DirectPrice;                
    pricingOptionTb .Increment = item.BidIncrement;
    pricingOptionTb .WarningCap = item.BidWarningCap;
}
else 
    context.PricingOptions.Add(PricingOption);

但是,鑒於您正在迭代一組 DTO,因此尚不清楚此處的“PricingOption”是什么。 此問題通常出現的地方是,當使用 Automapper 從 DTO 構造實體時,認為由於它具有現有 ID,將其添加到 DbContext 將被解釋為更新。 不幸的是,EF 只跟蹤跟蹤實體引用的更新,所以如果你給它一個對相同數據的不同引用,它將把它當作一個插入。

附帶說明:當加載您期望 0 或 1 個實體返回的實體時,請使用SingleOrDefault而不是FirstOrDefault 這提供了一個斷言,即只應找到(或不)1 條記錄。 使用First*方法時,您應該始終期望並允許多個匹配的可能性,並且在這種情況下始終包含OrderBy*子句以確保您的執行和選擇是可預測的。

更新:要處理更新或插入場景,您需要以下內容:

 Entities.PricingOption pricingOptionTb = context.PricingOptions.Where(a => a.ID.Equals(item.ID)).SingleOrDefault();

if (pricingOptionTb != null)
{                                                
    pricingOptionTb .DirectPrice = item.DirectPrice;                
    pricingOptionTb .Increment = item.BidIncrement;
    pricingOptionTb .WarningCap = item.BidWarningCap;
}
else 
{
    pricingOptionTb = new PricingOption
    {
        DirectPrice = item.DirectPrice,
        Increment = item.BidIncrement,
        WarningCap = item.BidWarningCap
    }
    context.PricingOptions.Add(pricingOptionTb);
}

理想情況下,盡管您應該明確地將 Add 與 Update 調用作為單獨的方法分開,並防止在行已存在的情況下添加請求,或在行不存在的情況下進行更新,或者考慮檢查傳入的 ID 或 DTO 上的 state 值。 即如果 ID = 0 它是一條新記錄,否則將其視為應該存在於數據庫中的現有項目。

if (item.ID == 0) // New item.
{
    // Consider adding a validation check for duplicate pricing options.
   var duplicatePricingOption == context.PricingOptions
       .Any(x => x.DirectPrice == item.DirectPrice
           && x.Increment == item.Increment
           && x.WarningCap == item.WarningCap);
   if (duplicatePricingOption)
       throw new ArgumentException("An existing pricing option exists for this combination.");

   var pricingOption = new PricingOption
   {
       DirectPrice = item.DirectPrice,
       Increment = item.BidIncrement,
       WarningCap = item.BidWarningCap
   };
   context.PricingOptions.Add(pricingOption);
}
else
{
    var pricingOption = context.PricingOptions.Where(a => a.ID.Equals(item.ID)).Single();

    pricingOption.DirectPrice = item.DirectPrice;                
    pricingOption.Increment = item.BidIncrement;
    pricingOption.WarningCap = item.BidWarningCap;
}

context.SaveChanges();

您應該只對新對象使用 Add 方法。 為了更新現有對象,您需要調用 Update 方法。

foreach (var item in pricingOptionDTO)
 {
     Entities.PricingOption pricingOptionTb = context.PricingOptions.Where(a => a.ID.Equals(item.ID)).FirstOrDefault();

        if (pricingOptionTb != null)
           {                                                
            pricingOptionTb .DirectPrice = item.DirectPrice;                
            pricingOptionTb .Increment = item.BidIncrement;
            pricingOptionTb .WarningCap = item.BidWarningCap;

            context.Set<PricingOptions>().Update(pricingOptionTb);
           }
         context.SaveChanges(); 
   }

您還可以將 object 的 state 設置為“已修改”

你需要這樣做:

if (pricingOptionTb != null)
{                                                
    pricingOptionTb.DirectPrice = item.DirectPrice;                
    pricingOptionTb.Increment = item.BidIncrement;
    pricingOptionTb.WarningCap = item.BidWarningCap;

    context.Set<Entities.PricingOption>().Attach(pricingOptionTb);
    context.Entry(entity).State = EntityState.Modified;
    context.SaveChanges();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM