[英]How to update a single property in Entity Framework Core
我只需要更新實體的一兩個屬性。 換句話說,我有一個帶有 Id、ParentId、Name 和 Description 的實體。
問題是當名稱更新時,如果描述已經存在於數據庫中,它就會被清除。
這是代碼:
internal void Update(ItemInfo itemInfo)
{
var item = new Item { Id = itemInfo.Id, ParentId = itemInfo.ParentId, Name = itemInfo.Name };
var entry = this.DbContext.Items.Attach(item);
if (item.ParentId != null) entry.Property(x => x.ParentId).IsModified = true;
if (!(String.IsNullOrWhiteSpace(item.Name))) entry.Property(x => x.Name).IsModified = true;
this.SaveChanges();;
}
我認為由於我將特定屬性設置為已修改,因此只會更新該屬性。
或者我應該首先從數據庫中獲取實體,然后只設置屬性並保存。 我想避免一次保存兩次訪問數據庫。
您可以執行以下操作以更新單個屬性:
internal void Update(ItemInfo itemInfo)
{
if (itemInfo == null) { throw new Exception($"item info was not supplied"); }
var itemInfoEntity = new ItemInfo()
{
Id = itemInfo.Id,
ParentId = itemInfo.ParentId,
Name = itemInfo.Name
};
dbContext.ItemInfo.Attach(itemInfoEntity);
dbContext.Entry(itemInfoEntity).Property(x => x.Id).IsModified = true;
dbContext.Entry(itemInfoEntity).Property(x => x.Id).IsModified = true;
dbContext.Entry(itemInfoEntity).Property(x => x.Id).IsModified = true;
dbContext.SaveChanges();
}
但是如果你只更新幾個屬性,那么我認為你不應該將整個對象作為參數發送,只需發送需要更新的屬性,如下所示:
internal void Update(id, parentId, name)
{
...
}
您真正追求的是並發處理。 當多個用戶同時編輯同一個對象時,第二個用戶將覆蓋第一個用戶的更改。
或者我應該首先從數據庫中獲取實體,然后只設置屬性並保存。
是的,但是為對象的每個屬性都設置一個控制器方法會非常乏味。 這就是為什么並發處理是最好的選擇。
此外,您的域模型應該與您的數據庫模型完全分開。 切勿直接在 Web 應用程序中使用實體。 您已經通過使用Item
實體(數據庫模型)和ItemInfo
類(域模型,用於處理后請求)來實現這一點。
首先向您的實體添加Timestamp
列:
internal class Item
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
[Timestamp]
[ConcurrencyCheck]
public byte[] ConcurrencyStamp { get; set; }
}
然后,在您更新實體的地方:
[Controller]
public class ItemController : Controller
{
private readonly DbContext dbContext;
public ItemController(DbContext dbContext)
{
this.dbContext = dbContext;
}
[HttpPost]
//[Authorize]
//[ValidateAntiForgeryToken]
public async Task<ActionResult<ItemInfo>> Update([FromBody] ItemInfo item)
{
var existingItem = dbContext.Items.SingleOrDefaultAsync(i => i.Id == item.Id);
if (Convert.ToBase64String(existingItem.ConcurrencyStamp) != item.ConcurrencyStamp)
{
var databaseValue = new ItemInfo
{
Id = existingItem.Id,
ParentId = existingItem.ParentId,
Name = existingItem.Name,
};
return StatusCode(Microsoft.AspNetCore.Http.StatusCodes.Status409Conflict, databaseValue);
}
// Set new properties
existingItem.Id = item.Id;
existingItem.ParentId = item.ParentId;
existingItem.Name = item.Name;
// Save changes
await dbContext.SaveChangesAsync();
// Now return the updated item
// Now you should map the entity properties back to a new domain model...
var result = new ItemInfo
{
Id = existingItem.Id,
ParentId = existingItem.ParentId,
Name = existingItem.Name,
ConcurrencyStamp = Convert.ToBase64String(existingItem.ConcurrencyStamp),
};
return Ok(item);
}
}
現在,當您嘗試從客戶端更新您的項目並收到 409Conflict 狀態代碼時,您應該決定如何處理此問題。 我選擇在相應的輸入框下方顯示數據庫值。
你可以在這里找到完整的實現
您必須首先從數據庫中獲取實體,然后更新實體。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.