我有一个典型的Web API,带有几个PUT / UPDATE端点。这些端点只是调用底层服务,并进行更新。
服务层具有典型的签名,例如Object Update(Object object)
。然后我做的是基本上运行以下伪代码:
var dbobject = _db.Object.Find(object.Id);
dbobject.Field1 = object.Field1;
dbobject.Field2 = object.Field2;
// continue for all fields
_db.SaveChanges();
return GetObjectById(object.Id);
然而,这对我来说是一个挑战。
假设我们有API的消费者。此消费者调用我的PUT端点(/api/Object/{id}
),有效负载是更新的对象。
但是,假设我们放置的对象不知道示例Field4
,那么在运行更新后此值将为NULL
。
我的问题是:
答案 0 :(得分:1)
作为可能的方法之一,可以使用NotifyPropertyChanged
和automapper
的混合
理念是在DTO对象中存储确切设置的字段,并保持填充默认值。并在映射中使用收集的数据。
例如DTO对象将是
public class Dto
{
private List<string> Changed = new List<string>();
public bool IsChanged(string field) => Changed.Contains(field);
private int _age;
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
// IMPORTANT: field name should fit main object field name
Changed.Add("Name");
}
}
public int Age
{
get { return _age; }
set
{
_age = value;
Changed.Add("Age");
}
}
}
我使用Next类进行测试
public class Human
{
public string Name { get; set; } = "DEFAULT";
public int Age { get; set; } = -1;
}
和automapper配置看起来像
cfg.CreateMap<Dto, Human>()
.ForAllMembers(s=> s.Condition(d=>d.IsChanged(s.DestinationMember.Name)));
这是一个简单的例子。但它仍然不能阻止将函数IsChanged
用于某些复杂/特定的逻辑,不仅使用字符串Expressions
/ MethodInfo
,还可以添加自定义属性并在automapper配置(DestinationMember
为MethodInfo
)
您可以从控制器中的Request.Properties
获取有关已传递字段的信息,而不是复杂的DTO对象(类型为ms_querynamevaluepairs
的键Dictionary<string, string>
)。