我正在开发一个通过 WCF 服务执行一些 CRUD 操作的应用程序。read 方法返回一个完整的实体,更新是通过遗留系统执行的,并且只应更新更改的值。
在不简单地发送键值对字典的情况下,为这种情况设计数据合约的最佳方法是什么?
我正在开发一个通过 WCF 服务执行一些 CRUD 操作的应用程序。read 方法返回一个完整的实体,更新是通过遗留系统执行的,并且只应更新更改的值。
在不简单地发送键值对字典的情况下,为这种情况设计数据合约的最佳方法是什么?
如果它有帮助,但不确定你在寻找什么......
在更新请求中,仅对不为空的字段进行操作。
此外,将任何非可空类型包装在可空结构中。
举个例子 ...
Update( Nullable<int> orderNumber,
Nullable<DateTime> orderDate,
Nullable<bool> isComplete )
{
if( orderNumber != null )
databaseRecord.OrderNumber = orderNumber;
if( orderDate != null )
databaseRecord.OrderDate = orderDate;
if( isComplete != null )
databaseRecord.IsComplete = isComplete;
}
我能想到的唯一另一件事是让你的组件持久化——即将它的状态持久化到文件或数据库中。这样,在更新时,您可以将先前的状态与传入的状态进行比较。我不确定这是一个好方法,因为它会引入更多的开销,而不仅仅是传递键值对。
从外面看,它可能看起来更 CRUDy 或其他什么,但从实际的角度来看,你最好只是传递一些关于哪些值发生了变化的指示。
您可以不理会数据合同并更新您的服务合同。只需将方法的必填字段表示为服务合同中的属性。如果服务联系发生变化,任何使用该服务的消费应用程序都必须更新,但消费应用程序将知道成功更新数据所需的内容。
这种方法有利也有弊,但是当我编写的方法不需要完整的数据合同时,我会使用它。
--因拼写错误而编辑--
最好的方法是使用属性字典,只需将您的实体表示为属性名称和值的字典。将所有更改保存在某个列表中,并传递包含所有更改属性的部分字典。
我认为这是最好的设计,
如果您想避免这种设计,请发送带有更改属性列表的整个实体。(为了节省运输,您可以将 null 放在其他属性上)
如果您不想更改服务合同签名,您可以将修改后的属性的名称推送到标题上
您可以使用 DataSet 来保存您的更改。将您的记录称为 DataSet,然后为记录分配一些值。DataSet.Tables[0].GetChanges() 将为您提供已更改的列。
我对如何实现这一点有两个想法;
让客户端发送原始实体和完整的更改实体,然后服务将找出更改了哪些属性。
使用类似于 Nullable 的模式,让我们用 IsModified 标志和 T 类型的 NewValue 属性将其称为 Modified。DataContract 的每个属性都属于这种类型,服务可以在执行更新时检查 IsModified 标志。
我们使用的旧系统有一个接受 String.Empty 来识别未修改字段的 api,一个“?” 字符用于指示对空字符串的更新。我真的不喜欢这样,api的用户被迫阅读文档,如果你真的想存储一个'?你不能。我希望我们的 webservice api 更加明确。
查看您的要求和陈述,在开始写下我对可能解决方案的愿景之前,我做了一些假设:
如果这是真的,那么问题在于 Update 方法缺少信息。所需的信息是“已更改”,如果存在第二个状态以进行比较,或者应该已经存在于要在后端更新的状态旁边,则可以推断出该信息。
由于当客户端将其数据发布到 WCF 服务时您只有“后端状态”(没有标志),我们应该如何确定发生了什么变化?显然,我们希望防止另一个“读取”往返来获取当前服务器状态并开始比较。
将原始和更改的状态从客户端发送到服务器是一种可能但繁重的解决方案。其次,客户端对这些信息不感兴趣,服务器才是。
加上这一切,我猜想更改“更新”操作输入参数的类型是最简单的方法。创建一个装饰器类,将“脏位”行为添加到原始实体。使用这个新类作为“更新”操作的输入参数。然后,您将可以在服务器中检查客户端发送的完整状态旁边的这个脏位。客户端的主要变化是“更新”操作所需的对象不再与“读取”方法提供的对象相同。为了减轻这种痛苦,我可能会创建一个装饰器类来添加所需的“脏位”处理。这仅需要更改对象实例化,同时维护客户端的接口签名(很少更改代码)。