I am currently looking at some code which basically reads data line-by-line from a file and calls an appropriate method on a WCF client for each line. My problem with the code is that a new client is created for each operation ie:
function CallSomeOp(line)
{
using (var client = new Client()
{
client.SomeOp(line);
}
}
This seems to make the client close the connection and reopen a new one for each line in the file which seems like a big overhead. What I would like to do is move the creation of the client outside the function and into initialization, so that multiple operations are called on one client, ie:
using (var client = new Client())
{
for(var line in lines)
{
CallSomeOp(line, client);
}
}
But I'm not sure if this is OK or not. Is there some problem with calling multiple operations on a client, ie will I eventually run out of memory or something?
An operation is typically stateless, so that's expected behaviour. You can change the InstanceContextMode though. This determines if a new instance is created with each call or that there is a single instance. The question is, should you? Like I said, a single call is typically stateless. Having just a single instance doesn't scale very well either. I'd suggest to keep InstanceContextMode to be PerCall, that way, for every call the webserver creates a single instance, I wouldn't worry too much about overhead. If overhead really does become a problem, maybe a service isn't what you need.
Then there's the ConcurrencyMode which allows you to specify multiple threads to be created.
As far as the client is concerned, you don't need to re-create it everytime you want to call an operation. Alternatively, you could also look at the ChannelFactory if both client and server have knowledge of the contract. This answer provides some detail.
It's definitely a good idea to reuse a WCF client across multiple calls, since there is indeed a cost in creating new instances of it, even if that's been improved in later versions.
The most important thing to be aware of when reusing a WCF client, though, is that if a service operation fails, the whole client will be put in a faulted state and can no longer be used.
You will have to take this into consideration in your client code. Depending on your requirements, one way to handle this situation could be to recreate the client proxy in case of failure and continue processing the input, like shown in this example:
var client = new ServiceClient();
foreach (var line in lines)
{
try
{
client.DoSomething(line);
}
catch
{
client.Abort();
client = new ServiceClient()
}
}
Note that you may also want to keep track of how many times the service call fails and with what type of exception, since in some situations it would make more sense to completely abort the operation instead of keep trying, e.g. when the remote service is not reachable.
Related
I have a WCF service and I have the following (simplified) class:
public class PerOperationSingleton : IDisposable
{
private static bool _hasInstance = false;
public PerOperationSingleton()
{
if(_hasInstance)
throw new InvalidOperationException("Cannot have multiple instances during a single WCF operation");
_hasInstance = true;
}
public void Dispose()
{
_hasInstance = false;
}
}
I guess, it's pretty self explanatory piece of code. I don't need a singleton for entire WCF service but only during a single operation call. If one instance of the PerOperationSingleton is disposed, it should be safe to create a new instance during the same WCF operation.
The problem is that I don't know how to make the _hasInstance variable to be effective only for one WCF operation. I know about [ThreadStatic], but I've heard that ASP.NET and WCF do not guarantee that an operation will be executed on a single thread - it might be transferred to another thread.
I definitely don't want my _hasInstance = true to move to thread pool and get incorrectly detected if some other operation picks that thread from the pool.
If WCF operation moves to another thread, I would like the _hasInstance variable to keep the "true" value if it was set.
And I don't want to change some global settings for my WCF service to avoid affecting the performance or get into some problems which will be hard to debug and solve later (I don't feel proficient enough in advanced ASP.NET and WCF topics).
I cannot store _hasInstance in session either because my client requested to disable .NET sessions for various reasons.
I would like the class PerOperationSingleton actually to be environment agnostic. It shouldn't really know anything about WCF or ASP.NET.
How do I make _hasInstance variable static during entire call of my WCF operation and don't affect other WCF operations?
I would consider using OperationContext to make you data "static" during the operation call.
Here is a similar discussion Where to store data for current WCF call? Is ThreadStatic safe?
According to this post, I am using a data context per call, so in each method of my WCF service, I use a using block to create a new data context.
But I have some doubts in the form to work in this way.
For example, I use a method getAllCLients() from my repository to get all the clients of the data base, then the service send to the client that call the method a list with all the clients. Then the user modify the information of some of them, three for example. The modify client perhaps I can add to a list that have the modified clients.
When I want to update this three clients, I can call a method updateClients() which receive a list of modified clients. How I am use a new data context per each method, in updateCients() get a new dataContext, without entities, so I think that I have to follow this steps:
1.- create a new data context which has the clients that I want to update. SO I need to specified the conditions for that. This is an extra operation (I get the clients before with the getAllClients() method), so I need to get again the clients.
2.- go throw the clients collection of the DBSet (I use EF 4.1) and change the information. This makes me to go throw the list that I receive from the client application too. So I must to go throw two lists. This needs resources.
3.- save the changes. This is needed anyway, so it has no required more work.
There is any way to make the step 2 easily? exist some method in dataContext to pass the values from my modified client to the client in the data context? I use POCO entities, perhaps it exists an easy way to do that.
Other question is about concurrency. If I control the concurrency with pesimistic concurrency that allow EF (with a timestamp field for example), is it better to call the updateClient() one for each client or better to pass a list with all the clients? I mean that if I use a list as parameter, if there is a concurrency issue with one client,the second for example, the first client will be update correctly, but the second not and the third neither. How can I notify to the user that there is problems with some clients?
To resume, I would like to know the best way to make updates when I have a short life datacontext.
Thanks.
Daimroc.
The service is disconnected scenario so when your client passes backs modified records you just need to process them as modified. You don't need to load all records from database for that.
public void SaveClients(List<Client> modifiedClients)
{
using (var context = new Context())
{
modifiedClients.ForEach(c =>
{
context.Entry(c).State = EntityState.Modified;
});
context.SaveChanges();
}
}
If you are using per call service and every service operation needs context you can move your context instancing to service constructor because service instance will live only to server single service call = you don't need using for every call. If you do that don't forget to implement IDisposable on your service to dispose context.
Other question is about concurrency. If I control the concurrency with
pesimistic concurrency that allow EF (with a timestamp field for
example), is it better to call the updateClient() one for each client
or better to pass a list with all the clients?
EF doesn't support pesimistic concurrency out of the box. Using timestamp is optimistic concurrency because it allows others to use the record. Pesimistic concurrency is application logic where other client is not able to select locked record for update.
The concurrency is resolved per record but the problem in this case is transaction. Each call to SaveChanges results in transaction used to process all changes in the database. So if any of your modified records is not up to date you will get concurrency exception and whole transaction is rolled back = no record is updated.
You can still overcome the issue by passing list of modified records to the service (reducing roundtrips between client and service is a best practice) but you can process each record separately by calling SaveChanges for every single record. Anyway this should be very carefully considered because each call to SaveChanges is like separate unit of work - is it really what you want?
Btw. the best practice is to make your service statless. You should avoid maintaining data between service calls and this example really doesn't need it.
I need to extract several header values at the start of each request and place them into a ClientContext object that can be injected into my application code by MEF. I am using Preview 5 of the WCF Web API and don't see a way to do this.
In 'standard' WCF, I would create a class that implements IExtension<OperationContext> and have the following property to wire it all together:
[Export(typeof(IClientContext)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public static ClientContextExtension Current
{
get
{
var operationContext = OperationContext.Current;
if (operationContext == null)
return null;
var extension = operationContext.Extensions.Find<ClientContextExtension>();
if (extension == null)
{
extension = new ClientContextExtension();
operationContext.Extensions.Add(extension);
}
return extension;
}
}
A custom DelegatingHandler calls ClientContextExtension.Current and sets the properties from the header values. Unfortunately, with WCF Web API, OperationContext.Current is always null!
I cannot figure out a way to make this work with the Web API. Any help is appreciated!!!
I've come up with a working solution but remain open to other options. First, some rationale behind the original approach...
Because WCF uses thread pooling, anything based on a per-thread model may (and will) have a lifetime that extends beyond an individual request. I needed a way to store client context information pulled from the HTTP headers for each request as the information will be different each time. This means I can't persist the context information per-thread because the thread will be re-used.
Or can I?
The flaw in my logic was that thread re-use was the problem. In reality, each thread is only every servicing a single request at one time thereby making any information in that thread isolated to that request. Therefore, all I need to do is make sure that the information is relavent to that request and my problem is solved.
My solution was to refactor the Current property to reference a private static field marked with the [ThreadStatic()] attribute, ensuring that each instance was specific to the thread. Then, in my DelegatingHandler, which executes for each request, I reset the properties of the object for that request. Subsequent calls to Current during that request return the request-specific information and the next request handled by the thread gets updated in the DelegatingHandler so as far as my other code is concerned, the context is per-request.
Not perfect, but it at least gets me up and running for the moment. As I said, I am open to other solutions.
UPDATE
Upon closer inspection, this solution is not working as there is no thread affinity between the DelegatingHandler and the service code that is making use of the context object. As a result, sometimes my call to retrieve the ThreadStatic object works as expected but on other occasions I get a new instance because the code is operating on a different thread than the handler.
So, disregard this solution. Back to the drawing board.
UPDATE TO MY UPDATE
After discussing my problem with Glenn Block, it turns out that it is just a matter of making sure the context is set on the same thread the request handler (the service) is executing. The solution is to use an HttpOperationHandler instead of a MessageHandler.
According to Glenn, message handlers operate asynchronously which means they could execute on a different thread from the request handler (service) so we should never do anything in a message handler that requires thread affinity. On the other hand, operation handlers run synchronously on the same thread as the request handler, therefore we can rely on thread affinity.
So, I simply moved my code from a MessageHandler to an HttpOperationHandler and have the desired results.
You can read a full explanation here: http://sonofpirate.blogspot.com/2011/11/modeling-client-context-in-wcf-web-api.html
You can try to use a
HttpOperationHandler<HttpRequestMessage, HttpRequestMessage>
There you should be able to access the headers.
I have a WPF appliction that uses WCF services to make calls to the server.
I use this property in my code to access the service
private static IProjectWcfService ProjectService
{
get
{
_projectServiceFactory = new ProjectWcfServiceFactory();
return _projectServiceFactory.Create();
}
}
The Create on the factory looks like this
public IProjectWcfService Create()
{
_serviceClient = new ProjectWcfServiceClient();
//ToDo: Need some way of saving username and password
_serviceClient.ClientCredentials.UserName.UserName = "MyUsername";
_serviceClient.ClientCredentials.UserName.Password = "MyPassword";
return _serviceClient;
}
To access the service methods I use somethingn like the following.
ProjectService.Save(dto);
Is this a good approach for what I am trying to do? I am getting an errorthat I can't track down that I think may be realted to having too many service client connections open (is this possible?) notice I never close the service client or reuse it.
What would the best practice for WCF service client's be for WPF calling?
Thanks in advance...
You're on the right track, I'd say ;-)
Basically, creating the WCF client proxy is a two-step process:
create the channel factory
from the channel factory, create the actual channel
Step #1 is quite "expensive" in terms of time and effort needed - so it's definitely a good idea to do that once and then cache the instance of ProjectWcfServiceFactory somewhere in your code.
Step #2 is actually pretty lightweight, and since a channel between a client and a service can fall into a "faulted state" when an exception happens on the server (and then needs to be re-created from scratch), caching the actual channel per se is less desirable.
So the commonly accepted best practice would be:
create the ChannelFactory<T> (in your case: ProjectWcfServiceFactory) once and cache it for as long as possible; do that heavy lifting only once
create the actual Channel (here: IProjectWcfService) as needed, before every call. That way, you don't have to worry about checking its state and recreating it as needed
UPDATE: "what about closing the channel?" asks Burt ;-) Good point!!
The acccepted best practice for this is to wrap your service call in a try....catch....finally block. The tricky part is: upon disposing of the channel, things can do wrong, too, so you could get an exception - that's why wrapping it in a using(....) block isn't sufficient.
So basically you have:
IProjectWcfService client = ChannelFactory.CreateChannel();
try
{
client.MakeYourCall();
}
catch(CommunicationException ce)
{
// do any exception handling of your own
}
finally
{
ICommunicationObject comObj = ((ICommunicationObject)client);
if(comObj.State == CommunicationState.Faulted)
{
comObj.Abort();
}
else
{
comObj.Close();
}
}
And of course, you could definitely nicely wrap this into a method or an extension method or something in order not to have to type this out every time you make a service call.
UPDATE:
The book I always recommend to get up and running in WCF quickly is Learning WCF by Michele Leroux Bustamante. She covers all the necessary topics, and in a very understandable and approachable way. This will teach you everything - basics, intermediate topics, security, transaction control and so forth - that you need to know to write high quality, useful WCF services.
Learning WCF http://ecx.images-amazon.com/images/I/41wYa%2BNiPML._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.jpg
The more advanced topics and more in-depth look at WCF will be covered by Programming WCF Services by Juval Lowy. He really dives into all technical details and topics and presents "the bible" for WCF programming.
Greetings, I would like to ask if creating Singleton to have only one active connection to db is a good idea. What i would like to do is:
1) I have a wcf service
2) wcf service gets data from db
3) i would like to create a singleton like this to have only one connection to db:
private static PersistanceSingleton _Instance;
public static PersistanceSingleton Instance
{
get
{
if (_Instance == null)
{
_Instance = new PersistanceSingleton();
}
return _Instance;
}
}
I know this is not an ideal singleton but i just wrote it for this post purpose.
I would like to have some persistance repositories here and which I will be instantiating them in constructor.
Inside my service class I would have the following code inside constructor
_DBPersistanceSingleton = PersistanceSingleton.Instance;
Then when some request comes (e.g. GetUsersRequest) i would like to do something like:
_DBPersistanceSingleton.GetUsers()
Before each call to db is executed I will also check whether SqlConnection is open or not.
Please let me know if this is a good practice. The reason why I think about this solution is because of large number of users that will be connecting to that service via client application
It's not a good practice to reuse SqlConnection like that. Open it when you need it and close it as soon as you're done with it. Connection pooling will work for you under the hood reusing the connection.
No, I'd strongly recommend you don't. What happens if multiple requests come in at the same time? They can't all use the same connection at the same, at best you'd just be introducing a big bottleneck.
Connection pooling is handled automatically for you, and takes the hassle away from you so you don't need to worry about it. Just open and close connections as needed.
Putting the sql connection aside...
This singleton pattern is not thread safe and is a bad idea to use in a multi-threaded application (as your WCF service is likely to be).
With this code, if multiple simultaneous requests arrive, it is possible that multiple instances will be created.