Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过实体框架和JSON(C#)动态更新某些属性_C#_Json_Entity Framework_Asp.net Core_Model Binding - Fatal编程技术网

通过实体框架和JSON(C#)动态更新某些属性

通过实体框架和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的数据

我有一个.NETCoreAPI,它应该使用EntityFrameworkCore更新数据库中的一个实体

当用户编辑现有条目时,编辑表单仅发回已编辑的数据,而不是完整的实体

假设我们有一家商店:

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