Показаны сообщения с ярлыком C#. Показать все сообщения
Показаны сообщения с ярлыком C#. Показать все сообщения

четверг, 30 мая 2013 г.

WCF Quotas

When using WCF and transferring rather big objects or collection of objects or objects with a big amount of inner properties through the network, you can encounter a problem something like here:

Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service

The underlying secure session has faulted before the reliable session fully completed. The reliable session was faulted.

Server stack trace:
   at System.Runtime.InputQueue`1.WaitQueueReader.Wait(TimeSpan timeout, T& value)
   at System.Runtime.InputQueue`1.Dequeue(TimeSpan timeout, T& value)
   at System.ServiceModel.Channels.InputQueueChannel`1.Dequeue(TimeSpan timeout, TDisposable& item)
   at System.ServiceModel.Channels.DuplexChannel.TryReceive(TimeSpan timeout, Message& message)
   at System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation,
   Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,
   ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
                                                                         …
When starting WCF service locally – the exception disappears and everything works clearly.
Here are quotas on the level of binding:
MaxBufferPoolSize, MaxBufferSize, MaxReceivedMessageSize, MaxArrayLength, MaxBytesPerRead, MaxDepth, MaxNameTableCharCount, MaxStringContentLength.


Another point is that WCF uses dataContractSerializer or xmlSerializer when transferring objects. DataContractSerializer has maxItemsInObjectGraph property limit. It has 65535 value by default.

Here is possible solution for this problem:

1.      In your server configuration file (App.config/Web.config) find your binding and set required properties that override default values and add dataContractSerializer setting in serviceBehavior section:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
<behaviors>
      <serviceBehaviors>
        <behavior name="Common">
          <serviceMetadata httpGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
        <bindings>
               <netTcpBinding>
       <binding name="YourBindingName"
                        maxBufferSize="2147483647"
                        MaxBufferPoolSize ="2147483647"
                        maxReceivedMessageSize="2147483647"
                        openTimeout="00:10:00"
                       receiveTimeout="00:10:00"
                       transactionFlow="true" >
          <reliableSession enabled="true" inactivityTimeout="00:10:00"/>
          <readerQuotas maxStringContentLength="2147483647"
                                      maxArrayLength="2147483647"
                                      maxBytesPerRead="2147483647"
                                      maxDepth="2147483647"
                                      MaxNameTableCharCount="2147483647"/>
          <security mode="Transport">
            <transport clientCredentialType="Windows"/>
          </security>
        </binding>
               </netTcpBinding>
        </bindings>
<services>
      <service behaviorConfiguration="Common" name="YourServiceName">
        <host>
          <baseAddresses>
            <add baseAddress="YourServiceBaseAddress" />
          </baseAddresses>
        </host>
        <endpoint name="YourEndpointName" address="" binding="netTcpBinding"
                           bindingConfiguration="YourBindingConfiguration" contract="YourContract" />
        <endpoint address="net.tcp://targetServer:777/Services/YourServiceName/mex"
                            binding="mexTcpBinding"
                            contract="IMetadataExchange" />
      </service>
</services>
        <client>
            <endpoint address="yourAddress"
                binding="netTcpBinding" bindingConfiguration="bindingName"
                contract="yourContract" name="endpointName">
                <identity>
                    <userPrincipalName value="yourUser@yourDomain.com" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>
2.      On the client size open configuration file and set the required options (client needs endpointBehaviors to be set):
<system.serviceModel>
    <behaviors>
    <endpointBehaviors>
        <behavior name="ClientBehavior">
            <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
    </endpointBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="YourBindingName"
          maxBufferSize="2147483647"
          maxReceivedMessageSize="2147483647"
          openTimeout="00:10:00"
          receiveTimeout="00:10:00"
          transactionFlow="true"
          transactionProtocol="OleTransactions">
          <reliableSession enabled="true" inactivityTimeout="00:10:00"/>
          <readerQuotas
                        maxStringContentLength="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxDepth="2147483647"
                        maxNameTableCharCount="2147483646"
                        />
          <security mode="Transport">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint
        address="YourServiceName"
        binding="netTcpBinding"
        bindingConfiguration=" YourBindingName "
        contract="YourContract"
        name="endpointName"
        behaviorConfiguration="ClientBehavior">
        <identity>
          <userPrincipalName/>
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

пятница, 1 марта 2013 г.

Logging and Tracing SQL Queries using Entity Framework 5.0 Code First DbContext


During the development of my last application, I had a problem I encountered when there was a need to look at all queries to our entity framework database. After a lot of googling time I didn’t find the solution that works fine for entity framework 5.0 database code first using DbContext (not ObjectContext or DataContext). After all – I have found the  library called Clutch, that you can install via NuGet and use inside your project. The solution is very simple and elegant and only this works with the given conditions. Only thing you need to do is to implement an interface IDbTracingListener. That is how it looks like in the Clutch:


namespace Clutch.Diagnostics.EntityFramework
{
  public interface IDbTracingListener
  {
    void CommandExecuting(DbTracingContext context);

    void CommandFinished(DbTracingContext context);

    void ReaderFinished(DbTracingContext context);

    void CommandFailed(DbTracingContext context);

    void CommandExecuted(DbTracingContext context);
  }
}

So add new class to your application:

    /// <summary>
    /// Implementation of IDbTracingListener
    /// Class is used for tracing all SQL Queries to the entity framework database
    /// </summary>
    public class DbTracingListener : IDbTracingListener
    {      
        public void CommandExecuting(DbTracingContext context)
        {
            //implementation if needed here..
        }

        public void CommandFinished(DbTracingContext context)
        {
            //implementation if needed here..
        }

        public void ReaderFinished(DbTracingContext context)
        {
            //implementation if needed here..
        }

        public void CommandFailed(DbTracingContext context)
        {
            Debug.WriteLine("\nFAILED\n " + context.Command.CommandText);
            // or Trace.WriteLine("\nFAILED\n " + context.Command.CommandText);
        }

        public void CommandExecuted(DbTracingContext context)
        {
            Debug.WriteLine("\nExecuted\n " + context.Command.CommandText);
            // or Trace.WriteLine("\nExecuted\n " + context.Command.CommandText);
        }
    }

Don’t forget to add using statements:

using System.Diagnostics;
using Clutch.Diagnostics.EntityFramework;

Inside methods like “CommandExecuted” you can do everything you want with SQL statements to your DB that you can get via context.Command.CommandText.
The last thind is to enable tracing in Global.asax file in Application_Start method (for ASP.NET MVC application. For any other – do it in the entry point):

// Enable Tracing queries
DbTracing.Enable();
// Adding the listener (implementation of IDbTracingListener)
DbTracing.AddListener(new DbTracingListener());