WCF服务-更新操作最佳实践

本文关键字:最佳 操作 更新 服务 WCF | 更新日期: 2023-09-27 18:19:49

假设我们有一个简单的DTO,要用作CustomerUpdate方法的输入参数:

[DataContract]
public class CustomerUpdateDTO
{
    [DataMember(IsRequired = true, Order = 0)]
    public int CustomerId { get; set; }
    [DataMember(Order = 1)]
    public string FirstName { get; set; }
    [DataMember(Order = 2)]
    public string LastName { get; set; }
    [DataMember(Order = 3)]
    public string Address { get; set; }
}

只需要一个文件——CustomerId——这是非常明显的,因为我们必须知道要更新哪个客户。我想实现以下目标:

如果传入的SOAP消息包含给定的值(例如:Joe),则表示客户端希望更新此属性。如果SOAP消息不包含值,则不应更新该值。如果属性的值应该被删除(为null),则客户端应该使用nil="true"属性显式声明(因此显式传递null值)。

示例:

<CustomerUpdateDTO>
  <CustomerId>1</CustomerId>
  <FirstName>Joe</FirstName>
  <Address xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</CustomerUpdateDTO>

这样格式化的消息意味着,客户端只想更新FirstName,保持LastName不变,并将地址设置为null。

问题是,在默认配置下,这样的消息被反序列化为:

CustomerId = 1
FirstName = "Joe"
LastName = null
Address = null

因此LastName和Address最终都是null。

有没有一种方法可以判断哪一个"null"是由于省略SOAP消息中的值而导致的,哪一个是显式设置的?

如果没有,在这种情况下,什么是"最佳实践"?

WCF服务-更新操作最佳实践

经过谷歌搜索,我终于找到了问题的答案:)

数据成员默认值,如何判断是否真的发送了什么?

这是一个非常优雅和简单的解决方案。现在我觉得很明显:)

[DataContract]
public class CustomerUpdateDTO
{
    private string firstName;
    public bool FirstNameSpecified { get; set; }
    ...
    [DataMember(Order = 1)]
    public string FirstName
    {
        get
        {
            return firstName;
        }
        set
        {
            FirstNameSpecified = true;
            firstName = value;
        }
    }
    ...
}

当SOAP消息被反序列化并且值存在时。。。指定的标志设置为true。

就这样!纯粹的敬畏:)

这样格式化的消息意味着,客户端只想更新FirstName,保持LastName不变,并将地址设置为null。

要么将更新操作分解为几个不同的更新操作:

class FirstNameUpdate
    public Customer as integer
    public FirstName as string
end class 
class LastNameUpdate
    public Customer as integer
    public LastName as string
end class
class AddressUpdate
    public Customer as integer
    public Address as string
end class

或者重新发送不会改变的已知值

dim Customer = Service.GetCustomer(10)
dim CustomerUpdate as new CustomerUpdateDTO with {
    .CustomerID = Customer.ID,
    .FirstName = "Joe",
    .LastName = Customer.LastName,
    .Address = Nothing}
Service.Update(CustomerUpdate)

注意,LastName取自Customer DTO,并被发送回CustomerUpdate DTO中的服务。