通过实体框架和JSON(C#)动态更新某些属性
我有一个.NETCoreAPI,它应该使用EntityFrameworkCore更新数据库中的一个实体 当用户编辑现有条目时,编辑表单仅发回已编辑的数据,而不是完整的实体 假设我们有一家商店:通过实体框架和JSON(C#)动态更新某些属性,c#,json,entity-framework,asp.net-core,model-binding,C#,Json,Entity Framework,Asp.net Core,Model Binding,我有一个.NETCoreAPI,它应该使用EntityFrameworkCore更新数据库中的一个实体 当用户编辑现有条目时,编辑表单仅发回已编辑的数据,而不是完整的实体 假设我们有一家商店: public class Shop { public int ShopID { get;set;} public string Name { get;set;} public string Address { get;set;} } 现在,用户编辑地址并保存它。发送回API的数据
public class Shop {
public int ShopID { get;set;}
public string Name { get;set;}
public string Address { get;set;}
}
现在,用户编辑地址并保存它。发送回API的数据将是ShopID和地址。但是,使用下面的模型绑定会将名称设置为NULL,这是合乎逻辑的,因为它实际上尚未传入
[Route("~/shop/[action]")]
public IActionResult Update([FromBody] Shop shop)
{
_context.Shops.Update(shop);
_context.SaveChanges();
return new JsonResult(new { result = true });
}
因此,由于我不知道哪些属性可能会被更新(实际上,还有很多属性),因此我需要某种方法来动态更新POST请求中发送的字段
提前感谢。DbSet
不包含方法Update
,因此您应该首先加载实体,然后更改属性值,然后调用SaveChanges
:
[Route("~/shop/[action]")]
public IActionResult Update([FromBody] Shop shop)
{
var shopData = _context.Shops.Single(s => s.Id == shop.ShopId);
if (shop.Name != null)
shopData.Name = shop.Name;
if (shop.Address != null)
shopData.Address = shop.Address;
_context.SaveChanges();
return new JsonResult(new { result = true });
}
由于检查和复制每个属性很烦人,您可以使用像Automapper这样的库:
[Route("~/shop/[action]")]
public IActionResult Update([FromBody] Shop shop)
{
var shopData = _context.Shops.Single(s => s.Id == shop.ShopId);
// Copying properties to existing object
mapper.Map<Shop, Shop>(shop, shopData);
_context.SaveChanges();
return new JsonResult(new { result = true });
}
[路线(“~/shop/[action]”)
公共IActionResult更新([FromBody]Shop)
{
var shopData=_context.Shops.Single(s=>s.Id==shop.ShopId);
//将属性复制到现有对象
地图(商店,商店数据);
_SaveChanges();
返回新的JsonResult(new{result=true});
}
有关跳过空属性的信息,请参见答案我没有测试它,但代码应该如下所示:
var entry = _context.Shops.Update(shop);
foreach (var property in entry.Entity.GetType().GetTypeInfo().DeclaredProperties)
{
var currentValue = entry.Property(property.Name).CurrentValue;
if (currentValue == null)
entry.Property(property.Name).IsModified = false;
}
如此接近,但仍有一段路要走。AutoMapper看起来很棒,我看了一下,但答案似乎过时了,最新版本为
.ForAllMembers(opt=>opt.Condition(srs=>!srs.IsSourceValueNull))代码>实际上不包含IsSourceValueNull。另外一个关于实现IValueResolver
的说法似乎也不正确,因为该接口现在需要三种类型的公共接口IValueResolver
。还是我太傻了?正如我所看到的,这里有一个答案:。对于所有成员(x=>x.Condition(y=>y!=null))
谢谢,看起来正在工作q为了参考,EF-Core实际上有方法。Update()。在他们的在线文档中似乎没有记录,但确实有效,并且在VS intellisense中。@Max,谢谢。我将尝试查找信息,尽管我不能简单地用谷歌搜索方法DbSet.Update
。