我想修改我的資料庫表(通知表)的列。相關的通知 Id 由視圖確定并使用 Ajax 呼叫發送回控制器。我的控制器代碼:
[HttpPost]
public JsonResult UpdateNotification(int notificationId, int userId)
{
string notificationText = _notificationRepository.GetNotificationById(notificationId).isSeen;
var myNotification = new Notification()
{
isSeen = string.Format("{0},{1}", notificationText, userId)
};
bool result = _notificationRepository.UpdateNotification(notificationId, myNotification);
if (result == true)
{
DeleteNotification(notificationId);
return Json(new { success = true});
}
else
{
return Json(new { success = false });
}
}
該行bool result = _notificationRepository.UpdateNotification(notificationId, myNotification);鏈接到存盤庫實作:
bool INotificationRepository.UpdateNotification(int selectedNotId, Notification notification)
{
try
{
var selectedNotification = new Notification()
{
notificationId = selectedNotId,
isSeen = notification.isSeen
};
context.Entry(selectedNotification).Property(x => x.isSeen).IsModified = true;
return true;
}
catch (Exception)
{
return false;
}
}
當我除錯時,出現以下錯誤context.Entry(selectedNotification).Property(x => x.isSeen).IsModified = true;并說:
System.InvalidOperationException:“無法跟蹤物體型別“通知”的實體,因為已經在跟蹤具有相同鍵值 {'notificationId'} 的另一個實體。附加現有物體時,請確保僅附加一個具有給定鍵值的物體實體。考慮使用“DbContextOptionsBuilder.EnableSensitiveDataLogging”來查看沖突的鍵值。
我嘗試notificationId使用從物體分離, context.Entry(selectedNotId).State = Microsoft.EntityFrameworkCore.EntityState.Detached但代碼停在這一行并且沒有任何反應。我該如何解決這個問題?
更新: 我使用相同的 DbContext 從資料庫表中讀取 notificationId(在視圖中)。
我在 Program.cs 中添加了作用域存盤庫:
builder.Services.AddScoped<INotificationRepository, NotificationRepository>();
uj5u.com熱心網友回復:
在實作諸如存盤庫之類的東西時,這是一個常見的問題,您在其中傳遞物體參考并且 DbContext 的范圍沒有明確定義。
問題是您對物體的重新定義太過分了。采取你的控制器方法:
string notificationText = _notificationRepository.GetNotificationById(notificationId).isSeen;
這是告訴存盤庫加載整個通知,然后檢索它的 Text 屬性。DbContext 可能正在跟蹤該實體,并且 DbContext 的范圍是請求的生命周期。當您呼叫 Update 方法時,仍會跟蹤由 GetNotificationById() 加載的實體,但您正在創建一個新的物體實體以傳遞給您的 update 方法,然后在您的 update 方法中創建另一個物體實體,都具有相同的 ID。
這是完全沒有必要的。我也無法理解你為什么要費力地更新通知,然后呼叫一個方法來洗掉通知?
[HttpPost]
public JsonResult UpdateNotification(int notificationId, int userId)
{
try
{
var notification = _notificationRepository.GetNotificationById(notificationId);
notification.IsSeen = string.Format("{0},{1}", notificationText, userId);
_context.SaveChanges();
return Json(new { success = true});
}
catch(Exception)
{
return Json(new { success = false});
}
}
由于存盤庫加載了一個物體,我們可以在該物體上使用更改跟蹤,然后使用作用域 DbContext 來保存更改。這確實違背了在 DbContext 之上添加存盤庫層的目的,因為您可以只使用 DbContext 本身獲取物體。通常使用作業單元模式,您將擁有更多類似的東西:
using (var scope = _unitOfWork.CreateScope())
{
var notification = _notificationRepository.GetNotificationById(notificationId);
notification.IsSeen = string.Format("{0},{1}", notificationText, userId);
scope.SaveChanges();
}
存盤庫有一種方法可以從它們被呼叫的 UoW 范圍內決議 DbContext。(即使用定位器或將范圍傳遞給每個方法呼叫)
不過,您要避免的主要事情是不斷更新同一行的物體類。(Id) 獲取一個物體,利用 EF 的內置更改跟蹤更新它的值,然后呼叫 SaveChanges()。如果您曾經遇到要更新的分離物體的情況,請首先檢查 DbContext 以查看它是否在附加之前跟蹤物體。例如,如果您修改傳遞到存盤庫的分離通知物體中的詳細資訊,并希望使用更新或附加并在物體/屬性上設定修改狀態:
bool INotificationRepository.UpdateNotification(Notification notification)
{
try
{
var existingNotification = context.Notifications.Local.SingleOrdefault(x => x.notificationId == notification.notificationId);
if (existingNotification != null)
{
existingNotification.isSeen = notification.isSeen;
}
else
{
context.Attach(notification);
context.Entry(selectedNotification).Property(x => x.isSeen).IsModified = true;
}
return true;
}
catch (Exception)
{
return false;
}
}
uj5u.com熱心網友回復:
為什么不使用更簡單的方法?什么時候可以重用存盤庫中的物體?下面的例子:
控制器代碼
[HttpPost]
public JsonResult UpdateNotification(int notificationId, int userId)
{
var notification = _notificationRepository.GetNotificationById(notificationId);
notification.isSeen = string.Format("{0},{1}", notificationText, userId);
bool result = _notificationRepository.UpdateNotification(notification);
if (result == true)
{
DeleteNotification(notificationId);
return Json(new { success = true});
}
else
{
return Json(new { success = false });
}
}
存盤庫實作
bool INotificationRepository.UpdateNotification(Notification notification)
{
try
{
context.Update(notification);
}
catch (Exception)
{
return false;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/416847.html
標籤:
下一篇:onget處理程式剃須刀頁面
