A WCF service which deals with large objects
Viewing WCF in its use as a way to do RPC between remote PCs you can nicely just send an object as a method parameter. This is easy to code but means whenever the object changes you send the whole thing, and also potentially means the receiver has to have extra logic to only act on changed fields. Or you can have a class which has one method per attribute on the object. This fine-grained approach is great for performance if you have a large class and normally only change one attribute. But it's a lot more code to write, and you have to maintain it every time the object gains another attribute.
Is there a better approach which can a开发者_如何学编程void having to write a load of copy-paste methods for each attribute, but also only sends attributes that actually change? Can we auto-generate the WCF service methods from a class/interface or something?
For example say we have the (pseudo) classes, and the aim is two applications want to keep in sync about people (I add a complex attribute List to make it a bit more like real life):
class Pet
{
String name;
AnimalType type;
}
class Person
{
int age;
float height;
string name;
List<Pet> pets
}
WCF by itself does not do that. There are many approaches to figure out changes, but it's in most cases developers duty.
The only predefined solution could be found is ADO.NET DataServices. This is actually RESTful WCF service wrapper for Entity Framework Datacontext from Microsoft. To be honest, you can actually use it not only with EF. On the client side you get a context, that tracks changes. When you submit changes, client only sends the concrete changes. But this limits you to HTTP transport and XML or JSON serialization, which does hit the performance on big objects.
There could be also some sort of event-driven solution, when you send a command to server with some meta data.
However you do it there is going to be overhead. It's up to you to decide what sort of overhead is most acceptable to you. Possible approaches:
- Ignore the problem and always send the full entity. The overhead here is the sheer amount of data being sent.
- Use ADO.NET Data Services. The overhead here is the data context, change tracking, and general "chattiness" of it all.
- Re-design your contracts to reduce the amount of data being passed. The overhead here is the additional complexity of the service interface.
Example of option 3:
class Person {
string Name;
PersonalData PersonalData;
MedicalData MedicalData;
List<Pet> Pets;
}
class PersonalData {
int Age;
string SSN;
}
class MedicalData {
float Weight;
float Height;
}
class Pet {
string Name;
AnimalType Type;
}
interface IPerson {
void Update(Person data, bool includePersonalData, bool includeMedicalData, bool includePets);
}
In the client code, if you don't want to update medical data, then you can pass false to the update method and not have to bother instantiating a MedicalData
object in the data. This cuts down on network traffic since the corresponding element in the InfoSet will be missing.
The solution really depends on what your binding constraints are. If you are forced to basicHttp bindings then ADO.Net DataServices might be the best approach as stated by Pavel and Christian. However, if NetTcp and other more complex bindings (WS*) are available, you could look into Reliable Messaging with Ordered Delivery. You could break down your responses into smaller chunks and put them back together on the other end. Also look into Streamed vs. Buffered transfer. Of course this requires a lot more work than ADO.Net DataServices but that makes it more fun, non?
Also, keep in mind Contract first development. Using parameterized methods in a web service will constrain you down the road and any changes you want to make will force a new version, even for any little change (e.g., an additional field returned).
精彩评论