Developer
Developer

Reputation:

WCF Close Connection using Anonymous Methods

In our project we are making WCF calls using the following Code.

// In generated Proxy we have..
public static ICustomer Customer
{
 get
  {
    ChannelFactory<ICustomer> factory = new ChannelFactory<ICustomer>("Customer");
    factory.Endpoint.Behaviors.Add((System.ServiceModel.Description.IEndpointBehavior)new ClientMessageInjector());
    ICustomer channel = factory.CreateChannel();
    return channel;
  }
}

and we have Service Proxy class which has the methods like

public static Datatable GetCustomerDetails(int id)
{
  return Services.Customer.GetCustomerDetails(id);
} 

public static void .SaveCustomerDetails (int id)
{
  Services.Customer.SaveCustomerDetails(id) ;
}

etc... which we use to make business calls.

Recently we found out that we need to "Close" the wcf connection and we are trying to find out away to do this without asking our developers to change too much of their code.

Please provide us with some suggestions which would help us achieve this goal

Upvotes: 3

Views: 1605

Answers (6)

Alex
Alex

Reputation: 2047

Do not create a new channel factory each time you create a channel. This is horrible from a performance point of view!

Upvotes: 0

bobbymcr
bobbymcr

Reputation: 24167

You are also leaking ChannelFactory<T> objects in the current approach. You should close these, too. If you use the static CreateChannel methods on ChannelFactory<T>, you will get auto-close behavior for the factory when the client closes so that could help solve that problem. Unfortunately, the static CreateChannel(string endpointConfigurationName) overload is protected, so you'd need to subclass ChannelFactory<T> in order to call it. (This might not be so bad overall.)

Now, if you want "auto-close" behavior of a channel and you are using a sessionful contract (SessionMode = SessionMode.Required), you can mark all your service operations "IsInitiating = true, IsTerminating = true" in the [OperationContract] attribute. Note that this will prevent you from ever being able to call more than one operation using the same ICustomer proxy. This might be the easiest option, if it is available to you.

As for your general approach, it is not considered good design for a property to do too much work, especially when it involves constructing new (expensive) objects and hitting the network. WCF proxies are nice abstractions and look like simple interface implementations, but they are not stateless and must be managed appropriately.

Upvotes: 1

marc_s
marc_s

Reputation: 755157

The accepted "best practice" for this case would be someting along the lines of this:

// create your client
ICustomer channel = CreateCustomerClient();

try
{
   // use it
   channel.GetCustomerDetails() ....

   (more calls)

   // close it
   channel.Close();
}
catch(CommunicationException commEx)
{
   // a CommunicationException probably indicates something went wrong 
   // when closing the channel --> abort it
   channel.Abort();
}

Typically, since the channel also implements "IDisposable", you might be tempted to just simply put it in a

using(ICustomer channel = CreateCustomerChannel()) 
{
   // use it
}

block - unfortunately, that could bomb out since there's a good chance that when attempting to call .Close() on your channel, you'll get another exception (which would go unhandled in this case).

Our moderator here, Marc Gravell, has an interesting blog post (don't(don't(use using)) on the topic, with an elegant solution to the problem.

Marc

Upvotes: 6

developer
developer

Reputation:

Unfortunately we use the generated Proxy methods which returns the channel and we use it in many places.So i was thinking there would be some way to "extend" the channel and close the connection after making the call(using extension methods).

Upvotes: 0

Eric King
Eric King

Reputation: 11744

The information in this question may also be helpful.

Upvotes: 0

Steven Sudit
Steven Sudit

Reputation: 19630

The right way to close connections is to put the client in a using block, or put the close in a finally. Otherwise, they will only get closed if no exception is thrown.

Upvotes: 0

Related Questions