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