Rohit Gupta

Engaging talk on Microsoft Technologies ....My Resume

  Home  |   Contact  |   Syndication    |   Login
  39 Posts | 0 Stories | 52 Comments | 0 Trackbacks

News



Twitter












Archives

Image Galleries

Personal

Wednesday, October 19, 2011 #

Policy injection block has been deprecated in Enterprise Library 5.0, however the ExceptionHandling application block contains ExceptionHandlingCallHandler which was usually found useful when used in conjunction with the Policy Injection App Block.
The purpose of this CallHandler is to handle exceptions using the policies defined in app.config/web.config for the ExceptionHandling app block.

One possible way of using the ExceptionHandlingCallHandler is to use the ExceptionHandlingCallHandler attribute on the methods that need Exception Handling. However the class must be enabled for interception by the Unity interceptors, since the ExceptionHandlingCallHandler attribute enables interception using the Unity Interception framework, hence the containing class should be enabled for interception by the Unity framework.

There are three possible ways of interception:
TransparentProxyInterceptor
InterfaceInterceptor
VirtualMethod interceptor

TransparentProxyInterceptor and InterfaceInterceptors are both interface interceptors and create a proxy around the class that needs interception.
InterfaceInterceptor is much better performing as compared to TransparentProxyInterceptors and hence we should choose InterfaceInterceptors except when we need intercept a class that is MarshalByRef object.
VirtualMethodInterceptor is a Type interceptor hence only works on abstract classes or concrete classes.
The following config shows how to enable a interface for interception:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
  <typeAliases>
    <typeAlias alias="ICountryService" type="Aurionpro.SCMProFit.Business.Kernel.API.Masters.ICountryService, Aurionpro.SCMProFit.Business.Kernel.API" />
  </typeAliases>
  <containers>
    <container>
      <extension type="Interception" />
      <register type="ICountryService" mapTo="Aurionpro.SCMProFit.Business.Kernel.Masters.APIServices.CountryService, Aurionpro.SCMProFit.Business.Kernel">
        <interceptor type="InterfaceInterceptor" />
        <policyInjection />
      </register>       
    </container>
  </containers>
</unity>

In the above unity config, we first need to define the sectionExtension for interception:
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
Then while registering the type with unity we also specify that we need this type to be intercepted. in the above example it uses InterfaceInterception for interception and uses the policyIntection Behavior for determining when the type should be intercepted.
Elsewhere in a common config I have defined the following policy :

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
  <containers>
    <container>
      <extension type="Interception" />
      <interception>
        <policy name="OperationContractPolicy">
          <matchingRule name="MatchOperationContract" type="Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule,Microsoft.Practices.Unity.Interception">
            <constructor>
              <param name="attributeType" value="System.ServiceModel.OperationContractAttribute, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" typeConverter="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.AssemblyQualifiedTypeNameConverter, Microsoft.Practices.EnterpriseLibrary.Common"/>
              <param name="inherited">
                <value value="false"/>
              </param>
            </constructor>
          </matchingRule>
        </policy>          
      </interception>
    </container>
  </containers>
</unity>

In the above config I have defined a policy injection behavior which uses a CustomAttributeMatchingRule to check if a method is decorated with a “OperationContract” attribute and if so then the type is selected for Interception by unity. Thus now if the method in ICountryService is also decorated with the ExceptionHandlingCallHandler attribute, then the Exception Handling for such a method will now be enabled.
==============================================================================================================
However if we don’t want to decorate a method with the ExceptionHandlingCallHandler attribute and we need to enable ExceptionHandling purely using Configuration, then we can create a CallHandler which implements ICallHandler and reads the Exception Handling policy configuration from the app.config/web.config. The following shows such an implementation:

public class ExceptionCallHandler : ICallHandler
{
    // Fields
    private ExceptionPolicyImpl exceptionPolicy;
    private int order;
 
    public ExceptionCallHandler(string exceptionPolicyName, int order)
    {
        this.exceptionPolicy = UnityContainerFactory.Instance.Resolve<ExceptionPolicyImpl>(exceptionPolicyName);
        this.order = order;
    }
 
    // Methods
    public ExceptionCallHandler(ExceptionPolicyImpl exceptionPolicy)
    {
        this.exceptionPolicy = exceptionPolicy;
    }
 
    public ExceptionCallHandler(ExceptionPolicyImpl exceptionPolicy, int order)
        : this(exceptionPolicy)
    {
        this.order = order;
    }
 
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        if (input == null)
        {
            throw new ArgumentNullException("input");
        }
        if (getNext == null)
        {
            throw new ArgumentNullException("getNext");
        }
        IMethodReturn return2 = getNext()(input, getNext);
        if (return2.Exception != null)
        {
            try
            {
                if (!this.exceptionPolicy.HandleException(return2.Exception))
                {
                    return2.ReturnValue = null;
                    return2.Exception = null;
                    if (input.MethodBase.MemberType == MemberTypes.Method)
                    {
                        MethodInfo methodBase = (MethodInfo)input.MethodBase;
                        if (methodBase.ReturnType != typeof(void))
                        {
                            return2.Exception = new InvalidOperationException(Resources.CantSwallowNonVoidReturnMessage);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                return2.Exception = exception;
            }
        }
        return return2;
    }
 
    // Properties
    public ExceptionPolicyImpl ExceptionPolicy
    {
        get
        {
            return this.exceptionPolicy;
        }
    }
 
    public int Order
    {
        get
        {
            return this.order;
        }
        set
        {
            this.order = value;
        }
    }
}

We need this class since we need an instance of ExceptionPolicyImpl and I used the same logic to create such an instance, as is specified in the ExceptionHandlingCallHandlerAttribute implementation.
Once we have this, just call this CallHandler to the unity config and all methods that satisfy the MatchingRule (in our case the CustomAttributeMatchingRule which looks for presence of OperationContract attribute on a method) would then call this ExceptionCallHandler. the example config will look like the following:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
  <containers>
    <container>
      <extension type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.EnterpriseLibraryCoreExtension, Microsoft.Practices.EnterpriseLibrary.Common" />
      <extension type="Interception" />
      <interception>
        <policy name="OperationContractPolicy">
          <matchingRule name="MatchOperationContract" type="Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule,Microsoft.Practices.Unity.Interception">
            <constructor>
              <param name="attributeType" value="System.ServiceModel.OperationContractAttribute, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" typeConverter="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.AssemblyQualifiedTypeNameConverter, Microsoft.Practices.EnterpriseLibrary.Common"/>
              <param name="inherited">
                <value value="false"/>
              </param>
            </constructor>
          </matchingRule>
          <callHandler name="EFCallHandler" type="Aurionpro.SCMFramework.Common.Repository.EntityFramework.Interceptor.EntityFrameworkCallHandler,Aurionpro.SCMFramework.Common">
            <constructor>
              <param name="order" value="10"/>
            </constructor>
          </callHandler>
          <callHandler name="ExceptionHandlingCallHandler" type="Aurionpro.SCMFramework.Common.Repository.EntityFramework.Interceptor.ExceptionCallHandler,Aurionpro.SCMFramework.Common">
            <constructor>
              <param name="exceptionPolicyName" value="UIExceptionPolicy"/>
              <param name="order" value="1"/>
            </constructor>
          </callHandler>
        </policy>          
      </interception>
    </container>
  </containers>
</unity>

In the above config we have explicitly added the following extension:
<extension type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.EnterpriseLibraryCoreExtension, Microsoft.Practices.EnterpriseLibrary.Common" />
and then added a reference to the created ExceptionCallHandler class do perform exception handling using the “UIPolicyException” policy . A sample Exception Handling policy looks like the following:

<exceptionHandling>
  <exceptionPolicies>
    <add name="UIExceptionPolicy">
      <exceptionTypes>
        <add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="ThrowNewException" name="Exception">
          <exceptionHandlers>
            <add name="Wrap Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WrapHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"  
                 exceptionMessage="Exception while updating entity"    
                 wrapExceptionType="Aurionpro.SCMFramework.Common.Repository.Exceptions.RepositoryException, Aurionpro.SCMFramework.Common,Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          </exceptionHandlers>
        </add>
      </exceptionTypes>
    </add>
  </exceptionPolicies>
</exceptionHandling>
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, October 18, 2011 #

When using the storage client library to access Azure Storage, it is recommended that we make use of the Async calls to execute queries against the Azure Tables/Blobs.
TableClient and BlobClient expose methods to execute queries asynchronously, for e.g.

blobClient.BeginListContainersSegmented : which retrieves the list of Blob Containers in our storage.
cloudTableClient.BeginListTablesSegmented() : which retrieves the list of tables in Azure strorage
and many more


Then there is CloudTableQuery class which exposes the BeginExecuteSegmented method which enables us to execute queries asynchronously.

The following example shows how to get the number of rows in a Azure Table.

   1: var context = new TableServiceContext(this.storageAccount.TableEndpoint.ToString(), this.storageAccount.Credentials);
   2: var query = context.CreateQuery<T>(this.tableName).AsTableServiceQuery();
   3:  
   4: if (condition != null)
   5:     query = Query.Where(condition).AsTableServiceQuery();
   6:  
   7: var results = new List<T>();
   8: if (query != null)
   9: {
  10:     //Using Storage Client Library Async API to execute query
  11:     using (var mre = new System.Threading.ManualResetEvent(false))
  12:     {
  13:         query.BeginExecuteSegmented((result) =>
  14:                                         {
  15:                                             var resultSegment =
  16:                                                 query.EndExecuteSegmented(result);
  17:                                             results.AddRange(resultSegment.Results);
  18:                                             while (resultSegment.HasMoreResults)
  19:                                             {
  20:                                                 resultSegment = resultSegment.GetNext();
  21:                                                 results.AddRange(resultSegment.Results);
  22:                                             }
  23:                                             mre.Set();
  24:                                         }, null);
  25:         mre.WaitOne();
  26:     }
  27: }
  28: return results.Count;

Note that currently with version 1.5 of the Azure SDK, there are some instances when the AsTableServiceQuery() extension method throws an exception complaining that the query parameter passed to the CloudTableQuery<T> constructor cannot be null.
This happens when the query is returning the entire table with no filter conditions.
At these times the cast to DataServiceQuery<T> fails and AsTableServiceQuery() throws an exception.
To get around this limitation cast the IQueryable<T> to CloudTableQuery<T> manually instead of calling the AsTableServiceQuery() extension.

   1: var context = new TableServiceContext(this.account.TableEndpoint.ToString(), this.account.Credentials);
   2: var query1 = context.CreateQuery<T>(this.tableName).AsTableServiceQuery();
   3: // if we call AsTableServiceQuery() again on query1 the "Variable cannot be null" exception is thrown
   4: var query = query1 as CloudTableQuery<AzureDummy>;
   5: query.BeginExecuteSegmented();

Here is an excellent post about using Asunc API for working with blobs : Accessing Blobs using Async API.

There some excellent posts by Neil Mackenzie on async API as well (which shows how to use BeginExecute() on DataServiceQuery<T> ): Queries in Azure Tables

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, September 22, 2011 #

In Windows Azure, we have the DiagnosticMonitorTraceListener which can be used for writing diagnostics to Local resource (like a local storage in the Worker or Web Role) which can then be ultimately stored in Windows Azure Table/Blob storage (transferred automatically by the Diagnostics Monitor in Windows Azure based on config settings).

We could either configure the Diagnostic Monitor using Code (in Role Startup) or we can use a config file for the same (called diagnostics.wadcfg). The code configuration for enabling transfer of Logs to Azure table storage looks something like this:

   1: String wadConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";
   2: String customContainerName = "wad-custom-container";
   3:  
   4: DiagnosticMonitorConfiguration dmc = DiagnosticMonitor.GetDefaultInitialConfiguration();
   5:  
   6: LocalResource localResource = RoleEnvironment.GetLocalResource(localResourceName);
   7: String logPath = Path.Combine(localResource.RootPath, "Logs");
   8: DirectoryConfiguration directoryConfiguration = new DirectoryConfiguration()
   9: {
  10:     Container = customContainerName,
  11:     DirectoryQuotaInMB = localResource.MaximumSizeInMegabytes,
  12:     Path = logPath
  13: };
  14: dmc.Directories.DataSources.Add(directoryConfiguration);
  15: dmc.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
  16:  
  17: dmc.Logs.BufferQuotaInMB = 100;
  18: dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
  19: dmc.Logs.ScheduledTransferLogLevelFilter =  LogLevel.Verbose;
  20: DiagnosticMonitor.Start(wadConnectionString, dmc);
If we need to use a configuration file instead the config file needs to be placed in the %RoleEntryPoint% folder in the case of web roles or within %RoleEntryPoint%\bin folder for WorkerRoles. Alternatively in Visual Studio, just include this diagnostics.wadcfg file in the root folder and set the following properties:

diagnostics.wadcfg

If we use the config file, then we don’t need any custom code in the Role Startup. The config file would look like the following:

   1: <DiagnosticMonitorConfiguration xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration" configurationChangePollInterval="PT1M" overallQuotaInMB="4096">
   2:   <DiagnosticInfrastructureLogs bufferQuotaInMB="100" scheduledTransferLogLevelFilter="Verbose" scheduledTransferPeriod="PT1H"/>
   3:   <WindowsEventLog bufferQuotaInMB="100" scheduledTransferLogLevelFilter="Verbose" scheduledTransferPeriod="PT1H">
   4:     <DataSource name="Application!*"/>
   5:   </WindowsEventLog>
   6:   <Logs bufferQuotaInMB="100" scheduledTransferLogLevelFilter="Verbose" scheduledTransferPeriod="PT1M"/>
   7:   <Directories bufferQuotaInMB="1024" scheduledTransferPeriod="PT1M">
   8:  
   9:     <!-- These three elements specify the special directories that are set up for the log types -->
  10:     <CrashDumps container="wad-crash-dumps" directoryQuotaInMB="256"/>
  11:     <FailedRequestLogs container="wad-frq" directoryQuotaInMB="256"/>
  12:     <IISLogs container="wad-iis-test" directoryQuotaInMB="256"/>
  13:  
  14:     <DataSources>
  15:       <DirectoryConfiguration container="wad-custom-container" directoryQuotaInMB="20">
  16:         <!--LocalResource specifies a path relative to a local resource defined in the service definition-->
  17:         <LocalResource name="CustomLoggingLocation" relativePath="Logs"/>
  18:       </DirectoryConfiguration>
  19:     </DataSources>
  20:   </Directories>
  21:  
  22:   <PerformanceCounters bufferQuotaInMB="100" scheduledTransferPeriod="PT20M">
  23:     <!-- The counter specifier is in the same format as the imperative diagnostics configuration API -->
  24:     <PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% Processor Time" sampleRate="PT10S"/>
  25:   </PerformanceCounters>
  26: </DiagnosticMonitorConfiguration>

This configuration is very similar to the default configuration that is stored in “wad-control-container” blob in Azure Blob storage for every deployment of our app.
Additionally, if we already have some custom configuration in “wad-control-container” we could get an instance of this configuration using RoleInstanceDiagnosticManager and then Update this configuration with the changes we need. Here is an example of doing the same:

   1: CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(wadConnectionString));
   2: var roleInstanceDiagnosticManager =
   3:     new RoleInstanceDiagnosticManager(cloudStorageAccount, RoleEnvironment.DeploymentId,
   4:                                       RoleEnvironment.CurrentRoleInstance.Role.Name,
   5:                                       RoleEnvironment.CurrentRoleInstance.Id);
   6:  
   7: DiagnosticMonitorConfiguration dmc = roleInstanceDiagnosticManager.GetCurrentConfiguration();
   8: LocalResource localResource = RoleEnvironment.GetLocalResource(localResourceName);
   9: String logPath = Path.Combine(localResource.RootPath, "Logs");
  10: DirectoryConfiguration directoryConfiguration = new DirectoryConfiguration()
  11: {
  12:     Container = customContainerName,
  13:     DirectoryQuotaInMB = localResource.MaximumSizeInMegabytes,
  14:     Path = logPath
  15: };
  16: dmc.Directories.DataSources.Add(directoryConfiguration);
  17: dmc.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
  18:  
  19: dmc.Logs.BufferQuotaInMB = 100;
  20: dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
  21: dmc.Logs.ScheduledTransferLogLevelFilter =  LogLevel.Verbose;
  22: roleInstanceDiagnosticManager.SetCurrentConfiguration(dmc);

Using DiagnosticMonitorTraceListener with Logging Application Block

We can use the same DiagnosticMonitorTraceListener as a TraceListener in Logging Application Block, the config for the same looks like this:

   1: <listeners>
   2:   <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
   3:       listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.SystemDiagnosticsTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
   4:        formatter="Text Formatter"
   5:        name="AzureDiagnostics">
   6:   </add>
   7: </listeners>

Then in C# code we could use such code for Logging:

   1: private static void Log(string module, string message, TraceEventType severity, params object[] args)
   2: {
   3:     string moduleSeverity = ConfigurationManager.AppSettings[module] ?? "";
   4:     if ((string.IsNullOrWhiteSpace(moduleSeverity) || moduleSeverity.Equals(severity.ToString().ToLower(), StringComparison.OrdinalIgnoreCase))
   5:         && Microsoft.Practices.EnterpriseLibrary.Logging.Logger.IsLoggingEnabled())
   6:     {
   7:         var msg = string.Format(message, args);
   8:         Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(msg, module, 1, 0, severity);
   9:     }
  10: }

The Sample configuration for Logging Application Block would look something like the following:

   1: <configuration>
   2:   <configSections>
   3:     <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
   4:   </configSections>
   5:   <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
   6:     <listeners>
   7:       <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
   8:           listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
   9:           source="SmartSAPConn" formatter="Text Formatter" log="" machineName="."
  10:           traceOutputOptions="None" />
  11:       <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  12:           listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.SystemDiagnosticsTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  13:            formatter="Text Formatter"
  14:            name="AzureDiagnostics">
  15:       </add>
  16:     </listeners>
  17:     <formatters>
  18:       <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  19:           template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
  20:           name="Text Formatter" />
  21:     </formatters>
  22:     <categorySources>
  23:       <add switchValue="All" name="General">
  24:         <listeners>
  25:           <add name="AzureDiagnostics" />
  26:         </listeners>
  27:       </add>
  28:     </categorySources>
  29:     <specialSources>
  30:       <allEvents switchValue="All" name="All Events" />
  31:       <notProcessed switchValue="All" name="Unprocessed Category" />
  32:       <errors switchValue="All" name="Logging Errors &amp; Warnings">
  33:         <listeners>
  34:           <add name="AzureDiagnostics" />
  35:         </listeners>
  36:       </errors>
  37:     </specialSources>
  38:   </loggingConfiguration>  
  39: </configuration>

Once we do this, at the configured interval in diagnostics.wadcfg file, the log records will get recorded in Azure table storage in “WADLogsTable” which gets created automatically by the DiagnosticsMonitor.
If we used Directory Logging then that would get persisted in Blob storage in a custom Blob container (in our case it would be wad-custom-container)

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, August 18, 2011 #

While developing applications for Windows Azure, we are all aware that we need to create Web and Worker Roles and use the Azure Compute Emulator (previously known as the Development Fabric) for running and testing applications in the local IIS server.

However to run unit tests against libraries that are being consumed from your web/worker roles we need to perform some preliminary steps before we can start using the CloudStorageAccount class within our Unit Tests.

The First step is to start the Storage Service if it is not already started which can be done in a method decorated with the AssemblyInitialze attribute.
The Second step is to call the CloudStorageAccount.SetConfigurationSettingPublisher method from a method decorated with the ClassInitialize attribute, so that we can then successfully use the CloudStorageAccount.FromConfigurationSetting("DataConnectionString") call from within any of the TestMethods.

The code to start the Storage Service can be something like the following:

   1: [AssemblyInitialize]
   2: public static void AssemblyInitialize(TestContext context)
   3: {
   4:     var count = Process.GetProcessesByName("DSService").Length;
   5:     if (count == 0)
   6:     {
   7:         var start = new ProcessStartInfo
   8:         {
   9:             Arguments = "/devstore:start",
  10:             FileName = @"C:\Program Files\Windows Azure SDK\v1.4\bin\csrun.exe"
  11:         };
  12:  
  13:         var proc = new Process { StartInfo = start };
  14:         proc.Start();
  15:         proc.WaitForExit();
  16:     }
  17: }

Before we can start using the _storageAccount from within our unit tests we need the following code to be configured and setup:

First in the app.config file in the AppSettings section we need to add the following entry:

   1: <configuration>
   2:   <appSettings>
   3:     <add key="DataConnectionString" value="UseDevelopmentStorage=true" />
   4:   </appSettings>
   5: </configuration>

Then in the ClassInitialize static method we need the following code:

   1: [ClassInitialize()]
   2: public static void Init(TestContext testContext)
   3: {
   4:     CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
   5:     {
   6:         var connectionString = ConfigurationManager.AppSettings[configName];
   7:         configSetter(connectionString);
   8:     });
   9: }

Finally in the TestMethod() we can use the _storageAccount and work directly against the Azure table/blob/queue storage as shown below:

   1: [TestMethod]
   2: public void FileExists(string pathWithFileName)
   3: {
   4:     pathWithFileName = pathWithFileName.Replace("\\", "/");
   5:     var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
   6:     _blobClient = storageAccount.CreateCloudBlobClient();
   7:     _blobClient.Timeout = new TimeSpan(1, 0, 0);
   8:     _blobClient.ParallelOperationThreadCount = 2;
   9:  
  10:     // Get the container
  11:     _blobContainer = _blobClient.GetContainerReference(_blobContainerName);
  12:     //Get the file from the blob container
  13:     var blob = _blobContainer.GetBlobReference(pathWithFileName);
  14:     Assert.Istrue(blob.Exists());
  15: }
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, February 16, 2011 #

Consider the following:
We have an account named MYDOMAIN\eholz. This accounts Active Directory Login Name changes to MYDOMAIN\eburrell
Now this user was a active user in a Sharepoint 2010 team Site, and had a userProfile using the Account name MYDOMAIN\eholz.
Since the AD LoginName changed to eburrell hence we need to update the Sharepoint User (SPUser object) as well update the userprofile to reflect the new account name.
To update the Sharepoint User LoginName we can run the following stsadm command on the Server:

STSADM –o migrateuser –oldlogin MYDOMAIN\eholz –newlogin MYDOMAIN\eburrell –ignoresidhistory

However to update the Sharepoint 2010 UserProfile, i first tried running a Incremental/Full Synchronization using the User Profile Synchronization service… this did not work. To enable me to update the AccountName field (which is a read only field) of the UserProfile, I had to first delete the User Profile for MYDOMAIN\eholz and then run a FULL Synchronization using the User Profile Synchronization service which synchronizes the Sharepoint User Profiles with the AD profiles.

Update: if you just run the STSADM –o migrateuser command… the profile also gets updated automatically. so all you need is to run the stsadm –o migrate user command and you dont need to delete and recreate the User Profile

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

If you facing the issue that the web Analytics Reports in SharePoint 2010 Central Administration is not updating data.

When you go to your site > site settings > Site Web Analytics reports or Site Collection Analytics reports 
You get old data as in the ribbon displayed "Data Last Updated: 12/13/2010 2:00:20 AM"

  • Please insure that the following things are covered:

    Insure that Usage and Data Health Data Collection service is configured correctly.
    Log Collection Schedule is configured correctly
    Microsoft Sharepoint Foundation Usage Data Import and Microsoft SharePoint Foundation Usage Data Processing Timer jobs are configured to run at regular intervals
    One last important Timer job is the Web Analytics Trigger Workflows Timer Job insure that this timer job is enabled and scheduled to run at regular intervals (for each site that you need analytics for).

    After you have insured that the web analytics service configuration is working fine and the Usage Data Import job is importing the *.usage files from the ULS LOGS folder into the WSS_Logging database, and that all the required timer jobs are running as expected… wait for a day for the report to get updated… the report gets updated automatically at 2:00 am in the morning… and i could not find a way to control the schedule for this report update job.

    So be sure to wait for a day before giving up :)
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, November 08, 2010 #

If you generate CAML using LINQ to SharePoint in Visual Studio 2010 then you might see this bug popup:

If you are writing a CAML query to filter records based on Date and Time, and this query is generated using LINQ To SharePoint then you will get the following CAML query generated:

<View>
  <Query>
    <Where>
        <And>
          <Eq>
            <FieldRef Name='Title' />
            <Value Type='Text'>{0}</Value>
          </Eq>
          <Lt>
            <FieldRef Name='QuoteTime' IncludeTimeValue='TRUE' />
            <Value Type='DateTime>{1}</Value>
          </Lt>
        </And>
     </Where>
  </Query>
  <RowLimit Paged='TRUE'>100</RowLimit>
</View>

However the above is incorrect since the IncludeTimeValue Attribute is on the wrong element. The correct CAML query is as follows:

<View>
  <Query>
    <Where>
        <And>
          <Eq>
            <FieldRef Name='Title' />
            <Value Type='Text'>{0}</Value>
          </Eq>
          <Lt>
            <FieldRef Name='QuoteTime' />
            <Value Type='DateTime' IncludeTimeValue='TRUE'>{1}</Value>
          </Lt>
        </And>
     </Where>
  </Query>
  <RowLimit Paged='TRUE'>100</RowLimit>
</View>

Note that the IncludeTimeValue attribute is on the Value Element and not the FieldRef element. Thus if you need to filter records based on Date & Time then include the “IncludeTimeValue” attribute on the Value Element.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, July 16, 2010 #

Here is the fix for the same:

1-Locate the Outlook Temporary Items folder by opening the Registry and locating HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\Outlook\Sec urity\OutlookSecureTempFolder Navigate to the value of this Key. It should be something like: %USERPROFILE%\Local Settings\Temporary Internet Files\OLK3D\ where OLK3D is some randomly generated string that always starts with OLK
2-Quit Outlook
3-Delete the contents of the folder
4-Launch Outlook

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, June 23, 2010 #

Some of the new Features in EF v4 are :

context.ContextOptions.LazyLoadingEnabled is “true” by default.
What this means is that if you access a Navigation Property (which returns either a EntityCollection or a EntityReference) of an Entity and if that Navigated Entity (or Entity collection) is not found in the ObjectContext then the ObjectContext automatically loads it when the NavigationProperty is accessed. This means additional round trip to the database for each Navigated entity.
If you need to turn off this LazyLoadingEnabled flag on the ObjectContext set the LazyLoadingEnabled flag in the OnContextCreated() partial method of the PEFEntities partial class you created like so :

   1: public partial class PEFEntities
   2: {
   3:     partial void OnContextCreated()
   4:     {
   5:         this.ContextOptions.LazyLoadingEnabled = false;
   6:     }
   7: }

ObjectSet<TEntity>
In EntityFramework v4.0 when you execute a ObjectQuery<> it returns a ObjectSet of Entities. In earlier versions of Entity Framework, the ObjectQuery when executed returned a ObjectQuery itself which we could then iterate through to get results.

context.ExecuteStoreCommand

This command can be used to execute SQL/PSQL commands that don't return any values for e.g. insert/delete statements.

   1: using (var context = new EFRecipesEntities())
   2: {
   3:     context.ExecuteStoreCommand("delete from chapter10.Product");
   4:     context.ExecuteStoreCommand("insert into chapter10.Product values ('Chai', 'Beverage')");
   5: }

context.ExecuteStoreQuery<TElement>
If you need to execute a SQL/PSQL that returns record sets then use context.ExecuteStoreQuery<TElement> where TElement can be an existing Entity in the CSDL of the EDMX file, or if the result does not map to an existing Entity in the CSDL then use context.ExecuteStoreQuery<DbDataRecord> to iterate over the columns of the returned results manually using indexers on DbDataRecord to access column values. Note that context.ExecuteStoreQuery<> returns a ObjectResult<TElement> which be iterated over only once as opposed to ObjectSet<T> or ObjectQuery<T> which can be iterated over multiple times.

   1: using (var context = new EFRecipesEntities())
   2: {
   3:     string sql = "select * from Chapter3.Student where Degree = @Major";
   4:     var args = new DbParameter[] { new SqlParameter { ParameterName = "Major", Value = "Masters" } };
   5:     var students = context.ExecuteStoreQuery<Student>(sql, args);
   6: }


context.Translate<>
EF v4 does not provide a DIRECT way to iterate over Multiple result sets returned from a Stored Proc/ SQL Query. One solution is to use SqlCommand object to execute and return a SQLDataReader which contains multiple result sets and pass this datareader to context.Translate<> method which materialzes the datareader results into Entity objects. If you use the correct overload of context.Translate<>(reader, entitySetName, MergeOption) then Translate also fixes relationship spans automatically (i.e. fixes associations between related entities automatically).
Here is an example :

   1: using (var context = new EFRecipesEntities())
   2: {
   3: var cs = @"Data Source=.;Initial Catalog=EFRecipes;Integrated Security=True";
   4: var conn = new SqlConnection(cs);
   5: var cmd = conn.CreateCommand();
   6: cmd.CommandType = System.Data.CommandType.StoredProcedure;
   7: cmd.CommandText = "Chapter3.GetBidDetails";
   8: conn.Open();
   9: var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
  10: var jobs = context.Translate<Job>(reader, "Jobs",
  11: MergeOption.AppendOnly).ToList();
  12: reader.NextResult();
  13: context.Translate<Bid>(reader, "Bids", MergeOption.AppendOnly).ToList();
  14:     foreach (var job in jobs)
  15:     {
  16:         Console.WriteLine("\nJob: {0}", job.JobDetails);
  17:         foreach (var bid in job.Bids)
  18:         {
  19:         Console.WriteLine("\tBid: {0} from {1}",
  20:         bid.Amount.ToString("C"), bid.Bidder);
  21:         }
  22:     }
  23: }
If we do not use the correct overload of context.Translate<> then, in the above example the Bids would never get materialized into objects since there will not exist any association between jobs and bids. Also note that we do not need to call .ToList() on the first context.Translate<Job>() method before we can call reader.NextResult(), since context.Translate<> merely returns ObjectResult<Job> which needs to be completely iterated over before NextResult() call can succeed.
Translate() requires that the DbDataReader have columns that match each property on the entity. This matching is done using simple name matching. If a column name can’t be matched to a property, Translate() will fail.

DefaultIfEmpty() is now supported with EF v4.

In earlier versions of Entity Framework DefaultIfEmpty() method was not supported on ObjectQueries hence it was difficult to create LinqToEntities queries which was a Left JOIN across collections. In EF v4 we surely have this capability, so left joins are easier to implement and use in LinqToEntities. Here is an example:
   1: var products = from p in context.Products
   2:     join t in context.TopSellings on
   3:     p.ProductId equals t.ProductId into g
   4:     from tps in g.DefaultIfEmpty()
   5:     orderby tps.Rating descending
   6:     select new
   7:     {
   8:         Name = p.Name,
   9:         Rating = tps.Rating == null ? 0 : tps.Rating
  10:     };
CreateSourceQuery()
CreateSourceQuery() to create a ObjectQuery() from a EntityCollection or EntityReference to delay load Navigation properties of Entities.
If a Entity “address” has a Navigation Property which returns a EntityReference  “contact” or EntityCollection “Streets” and if LazyLoadingEnabled =  false, then inorder to insure that the EntityReference/EntityCollection is delay loaded we can either call the .Load() method on the
“address” entity’s navigation property. The other option is to call CreateSourceQuery() on the navigation property and then access the EntityReference or iterate over the EntityCollection.
The advantage of using CreateSourceQuery() is that we can add further QueryBuilder methods like “Include” to the ObjectQuery<> created by the CreateSourceQuery() call. for e.g. address.Contact.CreateSourceQuery().Include(“Orders”) will not only load the contact EntityReference, but it will also load all Orders for the contact.
The other advantage of CreateSourceQuery() is that we can use filters to get only certain entries from the EntityCollection (as shown below).
Yet another advantage of using CreateSourceQuery() is that we can attach range of Entities to a EntityCollection, instead of attaching 1 entity at a time.
   1: var cust=context.Contacts.OfType<Customer>().First(); 
   2: var sq = cust.Reservations.CreateSourceQuery().Where(r => r.ReservationDate > new DateTime(2008,1,1)); 
   3: cust.Reservations.Attach(sq); 
Gotchas with using the .Include() Query Builder method:
    If the query on which the .Include() builder method has been used does projections or group joins then the Include with be ignored. Group Joins changes the result type of the query hence the Include() is ignored.
    Thus Include applies only to final query results. if Include is used in a subquery, join, or nested “from” clause it is ignored.
    Include() method is a extension method only on the ObjectQuery<T>. Thus if you need to execute the Include() extension method against a IQueryable<T> then we need to cast it to ObjectQuery<T> first.
    The Query Path used within a Include() must begin from a Navigation property of the Entity on which the Include is being used.

IsLoaded Property, Clear() and Load() methods.
When you call Clear() method on Navigation Property which is a EntityCollection, then the cleared entities do still remain in the ObjectContext, its just that they are no longer connected to the parent entity. for e.g. order.OrderItems.Clear() will empty the OrderItems collection of the order Entity, however the OrderItem Entities themselves will still remain in the ObjectContext. Thus if you need to reconnect the OrderItem entities for the order then we need to call order.OrderItems.Load(MergeOption.OverwtiteChanges) instead of order.Orderitems.Load() since the default merge option is MergeOption.AppendOnly.

If you are manually doing deferred loading then always used .IsLoaded Property on the Entity you are trying to Load before explicitly defer loading of the Entity.
Another thing to note about the IsLoaded Property is that say for e.g. for Order with OrderId 1 there are no OrderItems. Thus when you call .Load() on the order.OrderItems.Load() then the OrderItems collection will be null, however note that the .IsLoaded property of OrderItems will be true.

When you use the CreateSourceQuery() method to grab the query for loading the entity or entity collection, Entity Framework will not set IsLoaded when the query is executed

If a parent Entity has been Loaded using a specific MergeOption then all the navigation entities must also be loaded with the same MergeOption else the deferred Loading of the Navigation entities will fail.

Relationship-span and Associations
When EF loads an Entity it also loads any “associations” that are 0..1 or 1..1.”associations” are first-class objects like entities. EF creates 3 ObjectStateEntries on ObjectStateManager, 1 for the Entity, 1 for the Association and 1 for the Stub for the other end of the association that is not yet loaded. The stub has a valid EntityKey even though the entity itself has not yet been loaded.
When that other entity is loaded the first entities stub is automatically populated with this other entity which just got loaded and thus completes the association.
This automatic loading of the stub entity is called relationship-span.

QueryView… EntitySQL queries written in the MSL … when to use QueryViews:
QueryViews can be very handy when you need to create Entities using more complex Filter conditions.
Finally to be able to use these Entities created using QueryViews to be updateable use Stored procedures to map to the  Insert, Update and Delete Functions of each entity being created using the QueryView.

Using ObjectStateManager to retrieve Entities from the ObjectContext that not yet saved to the database:
Use the following code to retrieve all Entities from the OSM (ObjectStateManager) that are not in the Detached state (i.e. in the Added, Modified, Deleted or Unchanged states):

   1: public static class StateManagerExtensions
   2: {
   3: public static IEnumerable<T> GetEntities<T>(this ObjectStateManager manager)
   4:     {
   5:     var entities = manager
   6:     .GetObjectStateEntries(~EntityState.Detached)
   7:     .Where(entry => !entry.IsRelationship && entry.Entity != null)
   8:     .Select(entry => entry.Entity).OfType<T>();
   9:     return entities;
  10:     }
  11: }

Note that when you run queries directly against the ObjectContext to get Entities ( for e.g. context.Technicians.Include(“ServiceCalls”), they return only entities that currently exist in the database. It is important to note that when you add or delete entities from the object context, these changes are not reflected in results of queries against the object context (context.Technicians). These queries represent entities as they exist in the database, not what currently exist in the object context.

Attach() vs AddObject().
We can use AddObject() on the EntitySet or the ObjectContext to add new Entities to the collection. However we can also use Attach() to add new entities to the collection. However when adding Entities using Attach is a 2 step process. First we need to call EntitySet.Attach() to attach the entity to the ObjectContext. However after calling Attach() the EntityState of this entity is still “Unchanged”, thus we need to change the EntityState of this entity to Added using the ObjectStateManager by calling context.ObjectStateManager.ChangeObjectState(entity, EntityState.Added).

Model Functions:
Model functions are functions defined using EntitySQL in the Conceptual Model (CSDL of the EDMX file). An Example of a Model Function (defined as a child element of the <Schema Namespace="EFRecipesModel"> element in the CSDL):

   1: <Function Name="GetInvoices" ReturnType="Collection(EFRecipesModel.Invoice)" >
   2: <Parameter Name="invoices" Type="Collection(EFRecipesModel.Invoice)">
   3: </Parameter>
   4: <DefiningExpression>
   5: Select VALUE i
   6: from invoices as i where i.Amount > 300M
   7: </DefiningExpression>
   8: </Function>

=========================================================
Note the distinction of Model Functions….these are defined in the Conceptual Model i.e. CSDL section of the EDMX file, whereas the DefiningQuery is defined in the SSDL section of the EDMX file and uses TSQL, if querying SQL Server, and return Entities from the Store layer.
An Example of a DefiningQuery is :

   1: <EntitySet Name="vOfficeAddresses"
   2:  EntityType="BreakAwayModel.Store.vOfficeAddresses" store:Type="Tables"
   3:  store:Schema="dbo" store:Name="vOfficeAddresses">
   4:    <DefiningQuery>
   5:      SELECT
   6:       [vOfficeAddresses].[FirstName] AS [FirstName],
   7:       [vOfficeAddresses].[LastName] AS [LastName],
   8:       [vOfficeAddresses].[addressID] AS [addressID]
   9:      FROM [dbo].[vOfficeAddresses] AS [vOfficeAddresses]
  10:    </DefiningQuery>
  11: </EntitySet>
=========================================================
One can also define Custom functions in the Store Layer (SSDL section of EDMX file) which are treated as Stored procedures whose return types can be scalar properties, ComplexTypes or Entities defined in the Conceptual layer. An example of a Custom function in SSDL (effectively seen as Sproc in the Model browser), defined as child element of the <Schema> element:
   1: <Function Name="MembersWithTheMostMessages" IsComposable="false">
   2: <CommandText>
   3: select m.*
   4: from chapter10.member m
   5: join
   6: (
   7: select distinct msg.MemberId
   8: from chapter10.message msg where datesent = @datesent
   9: ) temp on m.MemberId = temp.MemberId
  10: </CommandText>
  11: <Parameter Name="datesent" Type="date" />
  12: </Function>

Here the result of this custom Function is mapped to the Member Entity type in the CSDL.
=========================================================
QueryView is another type of query which is defined in the MSL i.e. mapping layer of the EDMX file. QueryView is written using ESQL, queries the Store layer Entities and returns Conceptual layer Entity. An Example of the Query view:

   1: <EntitySetMapping Name="WebOrders">
   2: <QueryView>
   3: select value
   4: EFRecipesModel.WebOrder(o.OrderId,
   5: o.CustomerName,o.OrderDate,o.IsDeleted,o.Amount)
   6: from EFRecipesModelStoreContainer.WebOrder as o
   7: where (o.OrderDate > datetime'2007-01-01 00:00') ||
   8: (o.OrderDate between cast('2005-01-01' as Edm.DateTime) and
   9: cast('2007-01-01' as Edm.DateTime) and !o.IsDeleted) ||
  10: (o.Amount > 800 and o.OrderDate &lt;
  11: cast('2005-01-01' as Edm.DateTime))
  12: </QueryView>
  13: </EntitySetMapping>

QueryViews come in handy when you need to filter by multiple criteria (as shown above), or you need to implement Table per Hierarchy inheritance when the foreign key defined in the derived tables is not the primary key of the derived table.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

If you need to use one log4net file name for Messages having Level between WARN and ERROR and a different filename for Messages having Level between INFO AND DEBUG, then use the following log4net config:

   1: <log4net>
   2:     <appender name="RollingFileAppenderInfo" type="log4net.Appender.RollingFileAppender">
   3:       <file type="log4net.Util.PatternString" value="Results\%property{LogName}" />
   4:       <appendToFile value="true" />
   5:       <rollingStyle value="Size" />
   6:       <maxSizeRollBackups value="-1" />
   7:       <maximumFileSize value="10240KB" />
   8:       <staticLogFileName value="true" />
   9:       <countDirection value="1"/>
  10:       <threshold value="DEBUG"/>
  11:       <layout type="log4net.Layout.PatternLayout">
  12:         <conversionPattern value="%m%n" />
  13:       </layout>
  14:       <filter type="log4net.Filter.LevelRangeFilter">
  15:         <levelMin value="DEBUG" />
  16:         <levelMax value="INFO" />
  17:       </filter>
  18:       <filter class="log4net.Filter.DenyAllFilter"/>
  19:     </appender>
  20:  
  21:     <appender name="RollingFileAppenderError" type="log4net.Appender.RollingFileAppender">
  22:       <file type="log4net.Util.PatternString" value="%property{LogName}" />
  23:       <appendToFile value="true" />
  24:       <rollingStyle value="Size" />
  25:       <maxSizeRollBackups value="10" />
  26:       <maximumFileSize value="10240KB" />
  27:       <staticLogFileName value="true" />
  28:       <countDirection value="1"/>
  29:       <threshold value="WARN"/>
  30:       <layout type="log4net.Layout.PatternLayout">
  31:         <conversionPattern value="%d [%t] %-5p %c [%x] - %m%n" />
  32:       </layout>
  33:       <filter type="log4net.Filter.LevelRangeFilter">
  34:         <levelMin value="WARN" />
  35:         <levelMax value="ERROR" />
  36:       </filter>
  37:     </appender>
  38:  
  39:     <root>
  40:       <level value="DEBUG" />
  41:       <appender-ref ref="RollingFileAppenderInfo" />
  42:       <appender-ref ref="RollingFileAppenderError" />
  43:     </root>
  44:   </log4net>

Note here that I am using Dynamic logfile names so you need to call the following in your code to set up the Log4net File Names:

   1: GlobalContext.Properties["LogName"] = Log4netSetup.GetLog4NetLogFileName();
   2: XmlConfigurator.Configure(new FileInfo("CreateAssetCashFlows.exe.config"));

The Level’s in log4net are Off, FATAL, ERROR, WARN, INFO, DEBUG, ALL where OFF is the Highest Level and ALL is the Lowest Level.

Thus note that the following config is important :

   1: <threshold value="WARN"/>
   2: <filter type="log4net.Filter.LevelRangeFilter">
   3:   <levelMin value="WARN" />
   4:   <levelMax value="ERROR" />
   5: </filter>

The threshold parameter specifies that all Messages BELOW the Level WARN Will be ignored by this FileAppender. ( i.e. INFO, DEBUG & ALL Messages will be ignored)
The LevelRangeFilter states that Messages Between WARN & Error ONLY will be logged by this Appender.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, June 18, 2010 #

1…Works like a charm:
   1: DECLARE @SearchStr nvarchar(100)
   2:  
   3: SET @SearchStr = 'SEARCH_KEYWORD'
   4:  
   5: CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
   6:  
   7: SET NOCOUNT ON
   8:  
   9: DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
  10: SET  @TableName = ''
  11: SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
  12:  
  13: WHILE @TableName IS NOT NULL
  14: BEGIN
  15:     SET @ColumnName = ''
  16:     SET @TableName = 
  17:     (
  18:         SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
  19:         FROM     INFORMATION_SCHEMA.TABLES
  20:         WHERE         TABLE_TYPE = 'BASE TABLE'
  21:             AND    QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
  22:             AND    OBJECTPROPERTY(
  23:                     OBJECT_ID(
  24:                         QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
  25:                          ), 'IsMSShipped'
  26:                            ) = 0
  27:     )
  28:  
  29:     WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
  30:     BEGIN
  31:         SET @ColumnName =
  32:         (
  33:             SELECT MIN(QUOTENAME(COLUMN_NAME))
  34:             FROM     INFORMATION_SCHEMA.COLUMNS
  35:             WHERE         TABLE_SCHEMA    = PARSENAME(@TableName, 2)
  36:                 AND    TABLE_NAME    = PARSENAME(@TableName, 1)
  37:                 AND    DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
  38:                 AND    QUOTENAME(COLUMN_NAME) > @ColumnName
  39:         )
  40:  
  41:         IF @ColumnName IS NOT NULL
  42:         BEGIN
  43:             INSERT INTO #Results
  44:             EXEC
  45:             (
  46:                 'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
  47:                 FROM ' + @TableName + ' (NOLOCK) ' +
  48:                 ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
  49:             )
  50:         END
  51:     END    
  52: END
  53:  
  54: SELECT ColumnName, ColumnValue FROM #Results

2….Here is another TSQL code which helps in searching all stored procedures:

   1: SELECT Name FROM sys.procedures
   2: WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%ProcessLog%'

OR use (this will search sprocs, udfs, triggers etc. (not just sprocs)):

   1: SELECT object_name(id) FROM syscomments where text like '%ProcessLog%'

3….. Here is another SQL which is helpful. If you have a lot of columns in a table and you need to find columns which are of a particular data type (e.g. datetime) then we can use this:

   1: SELECT * FROM SYSCOLUMNS WHERE Id = OBJECT_ID('geneva_security_extract') AND XTYPE = 61

. you pass in the name of the table to the OBJECT_ID function. Hope this helps

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, June 07, 2010 #

If you need create Unit tests for internal methods within a assembly in Visual Studio 2005 or greater, then we need to add an entry in the AssemblyInfo.cs file of the assembly for which you are creating the units tests for. For e.g. if you need to create tests for a assembly named FincadFunctions.dll & this assembly contains internal/friend methods within which need to write unit tests for then we add a entry in the FincadFunctions.dll’s AssemblyInfo.cs file like so :
   1: [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("FincadFunctionsTests")]

where FincadFunctionsTests is the name of the Unit Test project which contains the Unit Tests.
However if the FincadFunctions.dll is a strongly named assembly then you will the following error when compiling the FincadFunctions.dll assembly :
     Friend assembly reference “FincadFunctionsTests” is invalid. Strong-name assemblies must specify a public key in their InternalsVisibleTo declarations.
Thus to add a public key token to InternalsVisibleTo Declarations do the following:
You need the .snk file that was used to strong-name the FincadFunctions.dll assembly.
You can extract the public key from this .snk with the sn.exe tool from the .NET SDK. First we extract just the public key from the key pair (.snk) file into another .snk file.
sn -p test.snk test.pub
Then we ask for the value of that public key (note we need the long hex key not the short public key token):
sn -tp test.pub
We end up getting a super LONG string of hex, but that's just what we want, the public key value of this key pair. We add it to the strongly named project "FincadFunctions.dll" that we want to expose our internals from. Before what looked like:

   1: [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("FincadFunctionsTests")]

Now looks like.

   1: [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("FincadFunctionsTests, 
   2: PublicKey=002400000480000094000000060200000024000052534131000400000100010011fdf2e48bb")]

And we're done. hope this helps

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, May 21, 2010 #

Suppose you need to generate the following XML:
   1: <GenevaLoader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   2: xsi:schemaLocation="http://www.advent.com/SchemaRevLevel401/Geneva masterschema.xsd" 
   3: xmlns="http://www.advent.com/SchemaRevLevel401/Geneva">
   4:   <PriceRecords>
   5:     <PriceRecord>
   6:     </PriceRecord>
   7:   </PriceRecords>
   8: </GenevaLoader>
Normally you would write the following C# code to accomplish this:
   1: const string ns = "http://www.advent.com/SchemaRevLevel401/Geneva";
   2: XNamespace xnsp = ns;
   3: XNamespace xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
   4:  
   5: XElement root = new XElement( xnsp + "GenevaLoader",  
   6:   new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName), 
   7:   new XAttribute( xsi + "schemaLocation", "http://www.advent.com/SchemaRevLevel401/Geneva masterschema.xsd"));
   8:  
   9: XElement priceRecords = new XElement("PriceRecords");
  10: root.Add(priceRecords);
  11:  
  12:     for(int i = 0; i < 3; i++)
  13:     {
  14:         XElement price = new XElement("PriceRecord");
  15:        priceRecords.Add(price);
  16:     }
  17:  
  18:     doc.Save("geneva.xml");
The problem with this approach is that it adds a additional empty xmlns arrtribute on the “PriceRecords” element, like so :
   1: <GenevaLoader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.advent.com/SchemaRevLevel401/Geneva masterschema.xsd" xmlns="http://www.advent.com/SchemaRevLevel401/Geneva">
   2:   <PriceRecords xmlns="">
   3:     <PriceRecord>
   4:     </PriceRecord>
   5:   </PriceRecords>
   6: </GenevaLoader>
The solution is to add the xmlns NameSpace in code to each child and grandchild elements of the root element like so :
   1: XElement priceRecords = new XElement( xnsp + "PriceRecords");
   2: root.Add(priceRecords);
   3:  
   4: for(int i = 0; i < 3; i++)
   5: {
   6:     XElement price = new XElement(xnsp + "PriceRecord");
   7:    priceRecords.Add(price);
   8: }
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

use this command for copying files using a wildcard from the GAC to a local folder.
xcopy c:\windows\assembly\Microsoft.SqlServer.Smo*.dll c:\gacdll /s/r/y/c

The above command will continue even it encounters any “Access Denied” errors, thus copying over the required files.

To copy files using the Windows explorer just disable the GAC Cache Viewer by adding a entry to the registry:
Browse to “HKEY_LOCALMACHINE\Software\Microsoft\Fusion”
Add a Dword called DisableCacheViewer. Set the value of it to 1.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, April 27, 2010 #


The previous posts on Entity framework are available here :
Entity Framework version 1- Brief Synopsis and Tips – Part 1
Entity Framework v1 … Brief Synopsis and Tips – Part 2

General Tips on Entity Framework v1 & Linq to Entities:

ToTraceString()

If you need to know the underlying SQL that the EF generates for a Linq To Entities query, then use the ToTraceString() method of the ObjectQuery class. (or use LINQPAD)
Note that you need to cast the LINQToEntities query to ObjectQuery before calling TotraceString() as follows:

   1: string efSQL = ((ObjectQuery)from c in ctx.Contact
   2:          where c.Address.Any(a => a.CountryRegion == "US")
   3:          select c.ContactID).ToTraceString();
================================================================================
MARS or MultipleActiveResultSet

When you create a EDM Model (EDMX file) from the database using Visual Studio, it generates a connection string with the same name as the name of the EntityContainer in CSDL. In the ConnectionString so generated it sets the MultipleActiveResultSet attribute to true by default. So if you are running the following query then it streams multiple readers over the same connection:

   1: using (BAEntities context = new BAEntities())
   2: {
   3:   var cons =
   4:       from con in context.Contacts
   5:       where con.FirstName == "Jose"
   6:       select con;
   7:   foreach (var c in cons)
   8:   {
   9:     if (c.AddDate < new System.DateTime(2007, 1, 1))
  10:     {
  11:       c.Addresses.Load();
  12:     }
  13:   }
  14: }

=================================================================================
Explicitly opening and closing EntityConnection

When you call ToList() or foreach on a LINQToEntities query the EF automatically closes the connection after all the records from the query have been consumed.
Thus if you need to run many LINQToEntities queries over the same connection then explicitly open and close the connection as follows:

   1: using (BAEntities context = new BAEntities())
   2: {
   3:   context.Connection.Open();
   4:   var cons = from con in context.Contacts where con.FirstName == "Jose"
   5:              select con;
   6:   var conList = cons.ToList();
   7:   var allCustomers =  from con in context.Contacts.OfType<Customer>()
   8:                       select con;
   9:   var allcustList = allCustomers.ToList();
  10:   context.Connection.Close();
  11: }

======================================================================
Dispose ObjectContext only if required
After you retrieve entities using the ObjectContext and you are not explicitly disposing the ObjectContext then insure that your code does consume all the records from the LinqToEntities query by calling .ToList() or foreach statement, otherwise the the database connection will remain open and will be closed by the garbage collector when it gets to dispose the ObjectContext.

Secondly if you are making updates to the entities retrieved using LinqToEntities then insure that you dont inadverdently dispose of the ObjectContext after the entities are retrieved and before calling .SaveChanges() since you need the SAME ObjectContext to keep track of changes made to the Entities (by using ObjectStateEntry objects). So if you do need to explicitly dispose of the ObjectContext do so only after calling SaveChanges() and only if you dont need to change track the entities retrieved any further.
=======================================================================
SQL InjectionAttacks under control with EFv1
LinqToEntities and LinqToSQL queries are parameterized before they are sent to the DB hence they are not vulnerable to SQL Injection attacks.
EntitySQL may be slightly vulnerable to attacks since it does not use parameterized queries. However since the EntitySQL demands that the query be valid Entity SQL syntax and valid native SQL syntax at the same time.
So the only way one can do a SQLInjection Attack is by knowing the SSDL of the EDM Model and be able to write the correct EntitySQL (note one cannot append regular SQL since then the query wont be a valid EntitySQL syntax) and append it to a parameter.
======================================================================
Improving Performance
You can convert the EntitySets and AssociationSets in a EDM Model into precompiled Views using the edmgen utility. for e.g. the Customer Entity can be converted into a precompiled view using edmgen and all LinqToEntities query against the contaxt.Customer EntitySet will use the precompiled View instead of the EntitySet itself (the same being true for relationships (EntityReference & EntityCollections of a Entity)). The advantage being that when using precompiled views the performance will be much better.

The syntax for generating precompiled views for a existing EF project is :
edmgen /mode:ViewGeneration /inssdl:BAModel.ssdl /incsdl:BAModel.csdl /inmsl:BAModel.msl /p:Chap14.csproj
Note that this will only generate precompiled views for EntitySets and Associations and not for existing LinqToEntities queries in the project.(for that use CompiledQuery.Compile<>)

Secondly if you have a LinqToEntities query that you need to run multiple times, then one should precompile the query using CompiledQuery.Compile method. The CompiledQuery.Compile<> method accepts a lamda expression as a parameter, which denotes the LinqToEntities query  that you need to precompile.
The following is a example of a lamda that we can pass into the CompiledQuery.Compile() method

   1: Expression<Func<BAEntities, string, IQueryable<Customer>>> expr = (BAEntities ctx1, string loc) =>
   2:                     from c in ctx1.Contacts.OfType<Customer>()
   3:                     where c.Reservations.Any(r => r.Trip.Destination.DestinationName == loc)
   4:                     select c;

Then we call the Compile Query as follows:

   1: var query = CompiledQuery.Compile<BAEntities, string, IQueryable<Customer>>(expr);
   2:  
   3: using (BAEntities ctx = new BAEntities())
   4: {
   5:     var loc = "Malta";
   6:     IQueryable<Customer> custs = query.Invoke(ctx, loc);
   7:     var custlist = custs.ToList();
   8:     foreach (var item in custlist)
   9:     {
  10:         Console.WriteLine(item.FullName);
  11:     }
  12: }

Note that if you created a ObjectQuery or a Enitity SQL query instead of the LINQToEntities query, you dont need precompilation for e.g.

   1: An Example of EntitySQL query :
   2: string esql = "SELECT VALUE c from Contacts AS c where c is of(BAGA.Customer) and c.LastName = 'Gupta'";
   3: ObjectQuery<Customer> custs = CreateQuery<Customer>(esql);
   1: An Example of ObjectQuery built using ObjectBuilder methods:
   2: from c in Contacts.OfType<Customer>().Where("it.LastName == 'Gupta'")
   3: select c

This is since the Query plan is cached and thus the performance improves a bit, however since the ObjectQuery or EntitySQL query still needs to materialize the results into Entities hence it will take the same amount of performance hit as with LinqToEntities.

However note that not ALL EntitySQL based or QueryBuilder based ObjectQuery plans are cached. So if you are in doubt always create a LinqToEntities compiled query and use that instead
============================================================
GetObjectStateEntry Versus GetObjectByKey
We can get to the Entity being referenced by the ObjectStateEntry via its Entity property and there are helper methods in the ObjectStateManager (osm.TryGetObjectStateEntry) to get the ObjectStateEntry for a entity (for which we know the EntityKey). Similarly The ObjectContext has helper methods to get an Entity i.e. TryGetObjectByKey().
TryGetObjectByKey() uses GetObjectStateEntry method under the covers to find the object, however One important difference between these 2 methods is that TryGetObjectByKey queries the database if it is unable to find the object in the context, whereas TryGetObjectStateEntry only looks in the context for existing entries. It will not make a trip to the database

          • =============================================================
            POCO objects with EFv1:
            To create POCO objects that can be used with EFv1. We need to implement 3 key interfaces:
            IEntityWithKey
            IEntityWithRelationships
            IEntityWithChangeTracker

            Implementing IEntityWithKey is not mandatory, but if you dont then we need to explicitly provide values for the EntityKey for various functions (for e.g. the functions needed to implement IEntityWithChangeTracker and IEntityWithRelationships).
            Implementation of IEntityWithKey involves exposing a property named EntityKey which returns a EntityKey object.

            Implementation of IEntityWithChangeTracker involves implementing a method named SetChangeTracker since there can be multiple changetrackers (Object Contexts) existing in memory at the same time.
   1: public void SetChangeTracker(IEntityChangeTracker changeTracker)
   2: {
   3:   _changeTracker = changeTracker;
   4: }

Additionally each property in the POCO object needs to notify the changetracker (objContext) that it is updating itself by calling the EntityMemberChanged and EntityMemberChanging methods on the changeTracker. for e.g.:

   1: public EntityKey EntityKey
   2: {
   3:   get { return _entityKey; }
   4:   set
   5:   {
   6:     if (_changeTracker != null)
   7:     {
   8:        _changeTracker.EntityMemberChanging("EntityKey");
   9:        _entityKey = value;
  10:        _changeTracker.EntityMemberChanged("EntityKey");
  11:      }
  12:      else
  13:        _entityKey = value;
  14:   }
  15: }
  16: =====================  Custom Property  ====================================
  17:  
  18: [EdmScalarPropertyAttribute(IsNullable = false)]
  19: public System.DateTime OrderDate
  20: {
  21:   get { return _orderDate; }
  22:   set
  23:   {
  24:     if (_changeTracker != null)
  25:     {
  26:       _changeTracker.EntityMemberChanging("OrderDate");
  27:       _orderDate = value;
  28:       _changeTracker.EntityMemberChanged("OrderDate");
  29:     }
  30:     else
  31:       _orderDate = value;
  32:   }
  33: }

Finally you also need to create the EntityState property as follows:

   1: public EntityState EntityState
   2: {
   3:   get  { return _changeTracker.EntityState;  }
   4: }

The IEntityWithRelationships involves creating a property that returns RelationshipManager object:

   1: public RelationshipManager RelationshipManager
   2: {
   3:   get
   4:   {
   5:     if (_relManager == null)
   6:       _relManager = RelationshipManager.Create(this);
   7:     return _relManager;
   8:   }
   9: }

============================================================
Tip : ProviderManifestToken – change EDMX File to use SQL 2008 instead of SQL 2005
To use with SQL Server 2008, edit the EDMX file (the raw XML) changing the ProviderManifestToken in the SSDL attributes from "2005" to "2008"
=============================================================
With EFv1 we cannot use Structs to replace a anonymous Type while doing projections in a LINQ to Entities query. While the same is supported with LINQToSQL, it is not with LinqToEntities. For e.g. the following is not supported with LinqToEntities since only parameterless constructors and initializers are supported in LINQ to Entities. (the same works with LINQToSQL)

   1: public struct CompanyInfo
   2: {
   3:     public int ID { get; set; }
   4:     public string Name { get; set; }
   5: }
   6: var companies = (from c in dc.Companies
   7:             where c.CompanyIcon == null
   8:              select new CompanyInfo { Name = c.CompanyName, ID = c.CompanyId }).ToList(); ;
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati