[英]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.