Monday, December 14, 2009

Stored Procedure Practices

Stored Procedure Practices:

 

  • Do not use Case statements in where clauses, they are a performance nightmare and hard for SQL to optimize.
  • You shouldn’t put IF statements that run different queries in a SP as the query optimizer will only optimize the branch that gets executed the first time.  When you take the alternate branch, you will have table scans for everything.
    • To get around this somewhat by having SP_WITH_RECOMPILE which will force a recompile each time – better solution is to split into separate SPs that can each be optimized and have the main SP call into the right one based on a simple/fast IF
  • Any hidden IO in the functions, should be unwound out of the function and put in the main query instead
  • As a general philosophy, from what we’ve seen in the database coding {or lack thereof in understanding how the query optimizer works in general} they should just be retrieving data from the database and the middle-tier or client should be doing all this display formatting.
  • A lot of function calls in the SPs should be unwound – again perhaps refactoring to the middle tier as opposed to putting function calls to outside C# .dlls in where clauses – you will see a cleaner code base and better options for performance enhancements.

 

Regards,

Arun

Friday, December 11, 2009

WWF vs BizTalk

Introduction

When I started studying Windows Workflow Foundation (WF), I was confused with the fact that there are lots of similarities between WF and BizTalk Server. Then I did some more studies and got hold of some good posts from Microsoft regarding the comparison of WF and BizTalk Server. Let me share what I summed up.

 

Windows Workflow Foundation

Windows Workflow Foundation (WF) is a programming model, set of tools, and runtime environment that allows one to write declarative workflows on the Windows platform to represent the execution model of your programs. The WF runtime is part of the .NET Framework, first appearing in .NET Framework 3.0, with improvements in .NET Framework 3.5.

 

Microsoft BizTalk Server

Microsoft BizTalk Server provides an efficient and effective way to integrate systems and businesses through manageable business processes, enabling them to automate and orchestrate interactions in a highly flexible and highly automated manner.


Microsoft BizTalk Server provides a development and run-time environment for business process management (BPM) and automation.

 

Fundamental Difference between WF and BizTalk Server

 

WF and BizTalk are not competing technologies. Windows Workflow Foundation and BizTalk are complementary technologies that serve different needs.

 

Windows Workflow Foundation

BizTalk Server

WF is a developer framework used to implement workflow inside an application.

BizTalk Server is a product that can be used to implement workflow across disparate applications.

WF is a framework that provides the building blocks needed to build workflow-based applications.

BizTalk is an integration server that includes the ability to add business process automation.

WF is a framework that provides developers with the base components they need to build the modules that will be used to automate processes.

BizTalk Server is a platform that provides developers with the pieces they need to automate business process.

WF does not have the inherent features or tools for tracking, administration and so on that is available with BizTalk.

BizTalk provides a lot of capabilities that are needed for serious business process automation that WF developers would have to write. To name a few, BizTalk has proven scalability, tracking, administration and transformation capabilities that a WF developer would need to write from scratch.

 

Comparison between WF and BizTalk Server

 

The following table shows the feature comparison between WF and BizTalk Server:

 

Feature

Windows Workflow Foundation

BizTalk Server

Hosting

Hosted in a custom application (client-side execution, but the client could be an ASP.NET application)

Server-side in the BizTalk process

Designer

Included in Visual Studio, or custom designers can be written

Included in Visual Studio

Scalability

Developer must implement

Well-proven, highly scalable

Transactional integrity

Developer must implement

Long running and atomic (ACID) transactions

Tracking infrastructure

Simple framework pieces provided that allow you to build the tracking infrastructure

Comprehensive Business Activity Monitoring infrastructure provided

Runtime modification of “in-flight” workflows

Yes, but developer must implement

No, workflows are defined at design time

Cross-platform integration capabilities

Not supported natively

Extensive adapters available

Composability

WF processes cannot directly invoke a BizTalk application, although you could indirectly by calling an orchestration that had been exposed as a Web service (for example), or perhaps by API usage

A BizTalk process could invoke a WF process via Web service call, or from a helper class or expression shape

Management and administration

Developer must implement

Extensive set of tools provided for IT pros to administer and track execution

Windows Communications Framework (formerly “Indigo”) support

Natively supported

Through an adapter, or could be called from an expression shape or helper class

Rules engine support

Yes

Yes

Extensible activities

Yes

No

Transformation capabilities

No

Yes

Programmability

WF is a framework. You must implement applications to use it.

BizTalk Server exposes APIs for most parts, and has numerous extensibility points such as pipeline components, adapters and “functoids” (out-of-the box and custom mapper components)

 

 

Friday, December 4, 2009

Microsoft Versions

Versions

Date  

Version

Remarks  

New ASP.NET related features 

January 16, 2002

(Time when joined CMC)

1.0

First version released together with Visual Studio .NET

  • Object oriented web application development supporting Inheritance, Polymorphism and other standard OOP features
    • Developers are no longer forced to use Server.CreateObject(...), so early-binding and type safety are possible.
  • Based on Windows programming; the developer can make use of DLL class libraries and other features of the web server to build more robust applications that do more than simply rendering HTML (i.e. exception handling)

 

April 24, 2003

1.1

Released together with Windows Server 2003

Released together with Visual Studio .NET 2003

 

  • Mobile controls
  • Automatic input validation

November 7, 2005

(Before Start of CCH)

2.0

Codename Whidbey released together with Visual Studio 2005 and

Visual Web Developer Express and

SQL Server 2005

  • New data controls (GridView, FormView, DetailsView)
  • New technique for declarative data access (SqlDataSource, ObjectDataSource, XmlDataSource controls)
  • Navigation controls
  • Master pages
  • Login controls
  • Themes
  • Skins
  • Web parts
  • Personalization services
  • Full pre-compilation
  • New localization technique
  • Support for 64-bit processors
  • Provider class model

 

November 21, 2006

(Time when about to leave Rishabh)

 

3.0

 

 

November 19, 2007

(Monetrix - Start)

3.5

Released with Visual Studio 2008 and Windows Server 2008

  • New data controls (ListView, DataPager)
  • ASP.NET AJAX included as part of the framework
  • Support for HTTP pipelining and syndication feeds.
  • WCF Support for RSS, JSON, POX and Partial Trust

 

August 11, 2008

(Monetrix – Finishing stage)

3.5 Service Pack 1

Released with Visual Studio 2008 Service Pack 1

  • Incorporation of ASP.NET Dynamic Data
  • Support for controlling browser history in an ASP.NET AJAX application
  • Capability to combine multiple Javascript files into a single file for more efficient downloading
  • New namespaces System.Web.Abstraction and System.Web.Routing

 

 

Reference: Link

 

Regards,

Arun

 

 

 

 

 

Tuesday, December 1, 2009

WS* Specifications & WSE

Hi,

 

We’ll go step by step.

 

  1. What are WS* Specifications
  2. What are WSE Enhancements

 

WS* Specifications

 

  • There are a variety of specifications associated with web services. These Web service specifications are occasionally referred to collectively as "WS-*". The reference term "WS-*" is more of a general nod to the fact that many specifications are named with "WS" as their prefix
  • These specifications are in varying degrees of maturity and are maintained or supported by various standards bodies and entities.
  • Specifications may complement, overlap, and compete with each other.

 

The specifications lie under different heads.

 

  1. Web Service Standards Listings
  2. XML Specifications
  3. Messaging Specifications
  4. Metadata Exchange Specifications
  5. Security Specifications
  6. Privacy
  7. Reliable Messaging Specifications
  8. Resource Specifications
  9. Web Services Interoperability organization (WS-I) Specifications
  10. Business Process Specifications
  11. Transaction Specifications
  12. Management Specifications
  13. Presentation Orientated Specification
  14. Draft Specifications

 

Here are the details on each.

 

Web Service Standards Listings

These sites contain documents and links about the different Web Services standards identified on this page.

 

    * IBM's Web Services Standards Page

    * Microsoft's Web Services Standards Page

    * World Wide Web Consortium's Web Services Activity

    * innoQ's WS-Standards Poster

    * OASIS Standards and Other Approved Work

    * XML CoverPages

    * Open Grid Forum Final Documents

 

XML Specifications

    * XML (eXtensible Markup Language)

    * XML Namespaces

    * XML Schema

    * XPath

    * XQuery

    * XML Information Set

    * XInclude

    * XML Pointer

 

Messaging Specifications

    * SOAP (formerly known as Simple Object Access Protocol)

    * SOAP Message Transmission Optimization Mechanism

    * WS-Notification

          o WS-BaseNotification

          o WS-Topics

          o WS-BrokeredNotification

    * WS-SoapOverUDP

    * WS-Addressing

    * WS-Transfer

    * WS-Eventing

    * WS-Enumeration

    * WS-MakeConnection

 

Metadata Exchange Specifications

    * WS-Policy

    * WS-PolicyAssertions

    * WS-PolicyAttachment

    * WS-Discovery

          o WS-Inspection

    * WS-MetadataExchange

    * Universal Description, Discovery, and Integration (UDDI)

    * WSDL 2.0 Core

    * WSDL 2.0 SOAP Binding

          o Web Services Semantics (WSDL-S)

    * WS-Resource Framework (WSRF)

 

Security Specifications

    * WS-Security

    * XML Signature

    * XML Encryption

    * XML Key Management (XKMS)

    * WS-SecureConversation

    * WS-SecurityPolicy

    * WS-Trust

    * WS-Federation

    * WS-Federation Active Requestor Profile

    * WS-Federation Passive Requestor Profile

    * Web Services Security Kerberos Binding

    * Web Single Sign-On Interoperability Profile

    * Web Single Sign-On Metadata Exchange Protocol

    * Security Assertion Markup Language (SAML)

    * XACML

 

Privacy

  • P3P

 

Reliable Messaging Specifications

    * WS-ReliableMessaging

    * WS-Reliability

    * WS-RM Policy Assertion

 

Resource Specifications

    * Web Services Resource Framework

    * WS-BaseFaults

    * WS-ServiceGroup

    * WS-ResourceProperties

    * WS-ResourceLifetime

    * WS-Transfer

    * Resource Representation SOAP Header Block

 

Web Services Interoperability organization (WS-I) Specifications

These specifications provide additional information to improve interoperability between vendor implementations.

 

    * WS-I Basic Profile

    * WS-I Basic Security Profile

    * Simple Soap Binding Profile

 

Business Process Specifications

    * WS-BPEL

    * WS-CDL

    * Web Services Choreography Interface

    * WS-Choreography

    * XML Process Definition Language

 

Transaction Specifications

    * WS-BusinessActivity

    * WS-AtomicTransaction

    * WS-Coordination

    * WS-CAF

    * WS-Transaction

    * WS-Context

    * WS-CF

    * WS-TXM

 

Management Specifications

    * WS-Management

    * WS-Management Catalog

    * WS-ResourceTransfer

    * WSDM

 

Presentation Orientated Specification

Web Services for Remote Portlets

 

Draft Specifications

WS-Provisioning Describes the APIs and Schemas necessary to facilitate interoperability between provisioning systems in a consistent manner using Web services

 

 

 

WSE Enhancements

 

  • WSE is an add-on to the Web Services, and enables to implement the above mentioned WS-* Web service specifications -  but chiefly in areas such as Security, Reliable Messaging, and Sending Attachments.
  • WSE provides extensions to the SOAP protocol i.e. SOAP protocol extensions and allows the definition of custom security, reliable messaging, policy, etc.
  • Developers can add these capabilities at design time using code or at deployment time through the use of a policy file.

 

There are multiple versions of WSE.

 

WSE 1.0

 

  • For .NET Framework 1.0 was released in December 2002.
  • It was based on the draft version of WS-Security.
  • It is not supported anymore and is not compatible with .NET 2.0.
  • It uses the older "XMLSOAP" namespace in contrast to the OASIS namespace used by WSS4J and WSE 2.0/3.0.

 

 

WSE 2.0

 

  • Released for Visual Studio .NET 2003 and the .NET Framework 1.1 in May 2004.
  • It introduced major secure communication improvements (signing and encryption of user-defined SOAP headers, Kerberos Security Context Tokens, delegated trust etc), a new lightweight messaging infrastructure, a new programming model, support for SOAP based messaging over TCP as an alternative to HTTP, a policy framework based on WS-Policy and WSDL, WS-Addressing, WS-Trust, WS-SecureConversation support.
  • WSE 2.0 can be used from within standalone executables and Windows services i.e. outside IIS in addition to ASP.NET applications.
  • It is also compatibile with .NET 2.0, however it does not have design time support with Visual Studio 2005.
  • It is not interoperable with WSE 3.0 and WCF.

 

WSE 3.0

 

·         Released in October 2005 and has design time support with Visual Studio 2005.

·         It includes policy framework enhancements including security based on policy assertions (associating CLR client proxies with policy files), turnkey security scenarios for securing end to end messages, extensibility mechanisms for user-defined policies in code and a simplified policy model applied to a message exchange instead of on a per-message level.

·         It supports updated Web services specifications and a native 64-bit runtime. WS-SecureConversation sessions can be cancelled explicitly and sessions are reliable and usable in web farm scenarios as Security Context Tokens can contain the original client authentication token when sent from the client to the service, which enable sessions to be re-established if lost, e.g. when a service's appdomain is reset.

·         WSE 3.0 is wire-level interoperable over HTTP with WCF and supports the same version of the WS-* specifications as WCF (WS-Security 1.1, SOAP 1.2, MTOM).

 

 

Note: It seems that there is no WSE 4.0 to work with VS2008. Instead, VS 2008 relies on WCF for the same functionality.

 

 

Hope this helps.

 

Reference: WS* Specifications, WSE

 

 

Regards,

Arun Manglick

 

 

 

 

 

Thursday, November 12, 2009

First Prize - Paper Dress Competition'

Hi,

 

Today my prince came first in the ‘Paper Dress Competition’ in class Nursery – Carnation.

The credit goes again to his Mumma. And also I thank to the Challenger Nursery School for taking such initiatives.

 

Regards,

Arun Manglick

Friday, November 6, 2009

Visual Studio .NET Platform Target Explained

Visual Studio .NET Platform ‘Target’ Explained

Written by: Darren Stokes

 

The Platform Target is an often overlooked option in the build configuration for Visual Studio 2005 and 2008 projects.  For C# projects, you will find this option on the Project Properties dialog under the build tab.  For VB.net projects, the setting is found on the Advanced Compiler Settings dialog which is made available via the Advanced Compile Options button on the Compile tab of the Project Properties.  The list of available options are:

 

  1. Any CPU
  2. x86
  3. x64
  4. Itanium

 

The meaning of these options is often misunderstood.  Based on their names, one might think that the compiler will generate code differently based upon the setting.  However, the C# and VB.net compilers only generate IL code that is taken to native code by the CLR at runtime using the just-in-time compiler (unless ngen is used but that is another discussion).  The fact is that this setting actually does not affect the build of the assembly in any way except to set the platform status information on the assembly's CLR header.  In other words, the Platform Target setting is meant to communicate the platform that the developer intends to be compatible with.

 

The default setting, Any CPU, means that the assembly will run natively on the CPU is it currently running on.  Meaning, it will run as 64-bit on a 64-bit machine and 32-bit on a 32-bit machine.  If the assembly is called from a 64-bit application, it will perform as a 64-bit assembly and so on.

 

If the project is set to x86, this means the project is intended to run only as a 32-bit process.  A 64-bit process will be unable to call into an assembly set as X86.  Reasons to set your project as x86 include dependencies upon native DLLs that are only available in 32-bit or making native calls assuming 32-bit .  Applications and assemblies marked for x86 can still run on 64-bit Windows.  However they run under WOW64.  Visual Studio itself runs under this emulation mode since it is a 32-bit application.

 

Setting the project to x64 will specify that the assembly must run under 64-bit Windows.  Attempting to run the assembly on 32-bit Windows or call the assembly from a 32-bit process will result in a runtime error.

 

The final, and likely least common, setting is Itanium.  This setting specifies that the assembly will only run on an Itanium processor.  The only reason to set your project for Itanium is if it has dependencies on native DLLs compiled specifically for the Itanium processor.

 

Developers should be aware that simply marking Platform Target of an assembly as Any CPU does not guarantee that it will run on both 32-bit and 64-bit Windows.  In fact, since Any CPU is the default setting, there are likely many applications that actually depend upon 32-bit processing but are not marked as such.  These assemblies will fail under 64-bit Windows when run from a 64-bit process so it is important to perform testing for your applications before users are migrated to 64-bit.  The somewhat increasing popularity of Vista x64 will soon elevate the importance of this type of testing.

 

Another point to be aware of when attempting to migrate to 64-bit processing for .Net applications is the dependency upon assemblies originally built using Visual Studio 2002 and 2003.  All assemblies targeting .Net 1.0 and 1.1 will be 32-bit only (x86) so these assemblies will need to be upgraded to newer versions, if available, or the functionality will need to be replaced in order for the process to execute as 64-bit.

Here are some excellent links on MSDN that should be required reading before migrating a complex project to 64-bit Windows:

 

Visual Studio 64-bit Applications

Migrating 32-bit Managed Code to 64-bit

 

 

Reference: Link

 

Thanks & Regards,

Arun Manglick || Senior Tech Lead

 

 

Thursday, November 5, 2009

Linq to SQL DataContext Lifetime Management

Linq to SQL DataContext Lifetime Management


87 comments

February 05, 2008 @ 1:55 am-  from Maui, Hawaii

 

Linq to SQL uses a DataContext to manage it's access to the database as well as tracking changes made to entities retrieved from the database. Linq to SQL has a persistent approach to managing its 'connection' to the database via this data context and it basically assumes that you use a single DataContext to make all of your data related access. This doesn't mean that it makes persistent connections to the database, but means that the DataContext instance maintains state about active result sets, which is especially important if change tracking is on which is the default.

This is somewhat contrary to other ORM tools which tend to have a static manager to which you pass entities or queries that are then returned. In that respect most other ORMs are stateless in their data connectivity and management object where LINQ to SQL clearly takes a connected approach where everything revolves around this single DataContext instance.  DataContext holds all the change management information and it makes it very difficult to transfer that context information to another DataContext. In short it's a very different approach and requires some thinking about how you create and manage the DataContext object.

BTW, the ADO.NET Entity framework too uses a similar connected approach with its ObjectContext object which also manages state persistently and requires that you keep the object around if you want to do things like track changes.

This raises some interesting questions on how to manage the lifetime of the DataContext object. There are a lot of options of how you can deal hanging on (or not) to the DataContext. Here are a few different approaches:

  • Create a new Context for each atomic operation (Application level management)
  • Create a global DataContext and handle all operations against this single DataContext object
  • Create a thread specific DataContext
  • Create a per business object DataContext

What doesn't work

The first thing to understand is if you are coming from another ORM manager you might be tempted to create a new context for each individual operation. Other ORMs typically have a static DataManager that load, save and otherwise manage entity instances. So you might create a context and load an entity and then modify it. Later you then create another instance and try to save this entity. Other ORMs typically have a method to load an entity and another to save one with a parameter for an entity to save. This approach really doesn't work with LINQ to SQL because of the change information is contained in the DataContext. LINQ to SQL really only has one way to commit updates which is by calling SubmitChanges() that takes all the changes stored on DataContext and writes them to the data store. There's no real way to abort changes either other than re-creating a new DataContext (which is another very odd design choice) and effectively abandoning the existing data context.

What this means is that if you plan on using LINQ to SQL like a traditional ORM - forget it. It just doesn't work well. You need to deal with the DataContext and a connected approach.

So let's talk about a few different approaches.

Create a new Context for each atomic operation

Basically with this approach you'd create a new DataContext for each atomic operation which would include potentially multiple queries and updates against a database. This would also have to include transactional operations such as running Transactions across multiple operations. The idea is that you perform your task or tasks that atomically belong together on a single instance of the DataContext and you then get rid of it (or don't reuse it at least) when you're done.

This approach works in many situations, but it can be problematic if you need to pass data objects or the data context itself around to other components in your application. For example, if you use business objects there's no real clean way to get a context passed between business objects.

In addition LINQ to SQL is very different in the way it deals with 'disconnected entities' - entities that have been detached. It's very difficult to do the truly disconnected entity approach that most other ORMs use where you use a central manager to create entities and then pass those entities back to the manager to update. LINQ to SQL's change manager marks objects in such a way that these objects can be reattached to another DataContext, so you have to use the same instance or use a complex approach (such as first serializing and deserializing an entity) to 'clear' the previous context and then Attach it. Attach is pretty ugly with lots of quirks that don't work so this should be reserved for only those truly disconnected (ie. Web Services etc.) situations. If at all possible you should try to stay connected to DataContext to get consistent behavior.

When I say 'atomic' here I'm talking about sticking with a connected instance of the Context and using that instance for one or more operations that are in the same application context - a single update or related set of updates that make up an operation. In Web applications this can often be the context of a single page or a single operation (like Save or Delete) in that page.

Create a global DataContext and handle all operations against this single DataContext object

It might seem very tempting to use a global DataContext that is used for all data access and indeed in some  types of applications like a Desktop application that might actually work. You can have a global context that is used for all data operations, and that single global data context can then manage all data access and update task.

At first this might seem a perfect situation. You get the benefit of just one instance and you globally have access to this single DataContext. But there are problems with this too. In some situations you might need to perform multiple data operations possibly on the same data that can't be handled in the context of a single DataContext. For example, say you update multiple sets of tables - for example say Invoices and Purchase Orders and before you update either you decide that you only need to update one of the two updated sets and discard the other. DataContext's global context approach really allows only two options which is the SubmitChanges() or recrate your data context. If you have two sets of updated data and you want to only update one set there's really no way to do this. In other words if you have multiple simulataneous data operations that might not be directly linked/atomic, you don't have the individual control to just update a part of the changed data unless you manually roll back the changes by undoing them which is pretty ugly.

In addition if you have a single instance of the DataContext you also need to consider that options applied then are global. Options such ObjectTrackingEnabled or DeferredLoadingEnabled can't be set easily without potentially affecting other operations that also need that same DataContext.

So while this appraoch can work in some situations - especially query only based  applications - it probably isn't a great idea, as it's just too coarse of a scope and gives too little control over the DataContext operation.

Create a Thread Specific DataContext

The 'global' approach above also couldn't work for Web applications because Web applications have multiple threads - one for each request - accessing data, often simultanouesly. But it might still be useful to a have a request specific DataContext that is tied to the active thread, or in the case of a Web request to the active ASP.NET HttpContext. Along the same lines it might also be useful to tie a DataContext to a specific thread so it can be reused on that thread.

The following is a DataContextFactory implementation that allows tieing to HttpContext.Current if available or the current thread context:

/// <summary>
/// This class provides several static methods for loading DataContext objects 
/// in a variety of ways. You can load the data context as normal one new instance
/// at a time, or you can choose to use one of the scoped factory methods that
/// can scope the DataContext to a WebRequest or a Thread context (in a WinForm app
/// for example).
/// 
/// Using scoped variants can be more efficient in some scenarios and allows passing
/// a DataContext across multiple otherwise unrelated components so that the change
/// context can be shared. 
/// </summary>
public class DataContextFactory
{
    /// <summary>
    /// Creates a new Data Context for a specific DataContext type
    /// 
    /// Provided merely for compleness sake here - same as new YourDataContext()
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <returns></returns>
    public static TDataContext GetDataContext<TDataContext>()
            where TDataContext : DataContext, new()
    {
        return (TDataContext)Activator.CreateInstance<TDataContext>();
    }
 
    /// <summary>
    /// Creates a new Data Context for a specific DataContext type with a connection string
    /// 
    /// Provided merely for compleness sake here - same as new YourDataContext()
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="connectionString"></param>
    /// <returns></returns>
    public static TDataContext GetDataContext<TDataContext>(string connectionString)
            where TDataContext : DataContext, new()
    {
        Type t = typeof(TDataContext);
        return (TDataContext) Activator.CreateInstance(t,connectionString) ;
    }
 
 
    /// <summary>
    /// Creates a ASP.NET Context scoped instance of a DataContext. This static
    /// method creates a single instance and reuses it whenever this method is
    /// called.
    /// 
    /// This version creates an internal request specific key shared key that is
    /// shared by each caller of this method from the current Web request.
    /// </summary>
    public static TDataContext GetWebRequestScopedDataContext<TDataContext>()
            where TDataContext : DataContext, new()
    {
        // *** Create a request specific unique key 
        return (TDataContext)GetWebRequestScopedDataContextInternal(typeof(TDataContext), null, null);
    }
 
    /// <summary>
    /// Creates a ASP.NET Context scoped instance of a DataContext. This static
    /// method creates a single instance and reuses it whenever this method is
    /// called.
    /// 
    /// This version lets you specify a specific key so you can create multiple 'shared'
    /// DataContexts explicitly.
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public static TDataContext GetWebRequestScopedDataContext<TDataContext>(string key)
                               where TDataContext : DataContext, new()
    {        
        return  (TDataContext) GetWebRequestScopedDataContextInternal(typeof(TDataContext),key, null);
    }
 
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public static TDataContext GetWebRequestScopedDataContext<TDataContext>(string key, string connectionString)
                               where TDataContext : DataContext, new()
    {
        return (TDataContext) GetWebRequestScopedDataContextInternal(typeof(TDataContext), key, connectionString);
    }
 
    /// <summary>
    /// Internal method that handles creating a context that is scoped to the HttpContext Items collection
    /// by creating and holding the DataContext there.
    /// </summary>
    /// <param name="type"></param>
    /// <param name="key"></param>
    /// <param name="connectionString"></param>
    /// <returns></returns>
    static object GetWebRequestScopedDataContextInternal(Type type, string key, string connectionString)                                   
    {
        object context;
 
        if (HttpContext.Current == null)
        {
            if (connectionString == null)
                context = Activator.CreateInstance(type);
            else
                context = Activator.CreateInstance(type, connectionString);
 
            return context;
        }
 
        // *** Create a unique Key for the Web Request/Context 
        if (key == null)
            key = "__WRSCDC_" + HttpContext.Current.GetHashCode().ToString("x") + Thread.CurrentContext.ContextID.ToString();
 
        context = HttpContext.Current.Items[key];
        if (context == null)
        {
            if (connectionString == null)
                context = Activator.CreateInstance(type);
            else
                context = Activator.CreateInstance(type, connectionString);
 
            if (context != null)
                HttpContext.Current.Items[key] = context;
        }
 
        return context;
    }
 
 
    /// <summary>
    /// Creates a Thread Scoped DataContext object that can be reused.
    /// The DataContext is stored in Thread local storage.
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public static TDataContext GetThreadScopedDataContext<TDataContext>()
                               where TDataContext : DataContext, new()
    {
        return (TDataContext)GetThreadScopedDataContextInternal(typeof(TDataContext), null, null);
    }
 
 
    /// <summary>
    /// Creates a Thread Scoped DataContext object that can be reused.
    /// The DataContext is stored in Thread local storage.
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public static TDataContext GetThreadScopedDataContext<TDataContext>(string key) 
                               where TDataContext : DataContext, new()
    {
        return (TDataContext)GetThreadScopedDataContextInternal(typeof(TDataContext), key, null);
    }
 
 
    /// <summary>
    /// Creates a Thread Scoped DataContext object that can be reused.
    /// The DataContext is stored in Thread local storage.
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    static object GetThreadScopedDataContextInternal(Type type, string key, string ConnectionString) 
    {
        if (key == null)
            key = "__WRSCDC_" + Thread.CurrentContext.ContextID.ToString();
 
        LocalDataStoreSlot threadData = Thread.GetNamedDataSlot(key);
        object context = null;
        if (threadData != null)
            context = Thread.GetData(threadData);
 
        if (context == null)
        {
            if (ConnectionString == null)
                context = Activator.CreateInstance(type);
            else
                context = Activator.CreateInstance(type,ConnectionString);
 
            if (context != null)
            {
                if (threadData == null)
                    threadData = Thread.AllocateNamedDataSlot(key);
 
                Thread.SetData(threadData, context);
            }
        }
 
        return context;
    }
 
 
    /// <summary>
    /// Returns either Web Request scoped DataContext or a Thread scoped
    /// request object if not running a Web request (ie. HttpContext.Current)
    /// is not available.
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="key"></param>
    /// <param name="ConnectionString"></param>
    /// <returns></returns>
    public static TDataContext GetScopedDataContext<TDataContext>(string key, string connectionString)
    {
        if (HttpContext.Current != null)
            return (TDataContext) GetWebRequestScopedDataContextInternal(typeof(TDataContext), key, connectionString);
 
        return (TDataContext)GetThreadScopedDataContextInternal(typeof(TDataContext), key, connectionString);
    }
 
    /// <summary>
    /// Returns either Web Request scoped DataContext or a Thread scoped
    /// request object if not running a Web request (ie. HttpContext.Current)
    /// is not available.
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public static TDataContext GetScopedDataContext<TDataContext>(string key)
    {
        if (HttpContext.Current != null)
            return (TDataContext)GetWebRequestScopedDataContextInternal(typeof(TDataContext), key, null);
 
        return (TDataContext)GetThreadScopedDataContextInternal(typeof(TDataContext), key, null);
    }
 
    /// <summary>
    /// Returns either Web Request scoped DataContext or a Thread scoped
    /// request object if not running a Web request (ie. HttpContext.Current)
    /// is not available.
    /// </summary>
    /// <typeparam name="TDataContext"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public static TDataContext GetScopedDataContext<TDataContext>()
    {
        if (HttpContext.Current != null)
            return (TDataContext)GetWebRequestScopedDataContextInternal(typeof(TDataContext), null, null);
 
        return (TDataContext)GetThreadScopedDataContextInternal(typeof(TDataContext), null, null);
    }
 
}

This approach might be a little more palatable than the global approach in the last bullet, especially for Web applications in that single page requests in a Web app typically stay within a specific range of related operations that can often be accomplished within a single data context. Using this approach lets you create a single DataContext that can be easily shared for a single page request.

The class above basically lets you create data contexts in HttpContext's Item collection or on a ThreadContext bag. These objects are then generically accessible by name from anywhere that has access to the static DataContextFactory.

In essence this is a variation of the global scheme but one that is a bit more generic and even easy enough to hook up so that you can use several DataContexts side by side easily.

Because this is tied to a static factory object  it also makes it much easier to share these instances between components. You can access these shared objects both from the application layer as well as from a business layer without having to track an instance in your own code.

Create a per Business Object instance of DataContext

Another semi-persistent approach is to use a DataContext object that's hung off a business object. In this way you have a business object and a related DataContext that ties operations of that business object to a specific DataContext. Presumably your business object's operations would be fairly atomic in nature and so you effectively can wrapper the business object around the DataContext. If for some reason you need two instances that perform tasks side by side with different DataContext options you could simply fire up another business object instance and configure that independently.

The idea is that each business object manages its own DataContext instance since a business object is already a typical unit of related operations. So a typical method in a business object then has direct access to the data context:

/// <summary>
 /// Gets a list of recent entries 
 /// </summary>
 /// <param name="userPk"></param>
 /// <param name="Count"></param>
 /// <returns></returns>
 public IQueryable<EntryEntity> GetEntries(int userPk)
 {
    IQueryable<EntryEntity> q =
        from e in this.Context.EntryEntities                
        orderby e.TimeIn descending
        select e;
 
    return q;
 }

The other advantage of this approach is that the DataContext is effectively wrapped up inside of the business object. In this way the business object controls DataContext instantiation and destruction, and more importantly you can pass the data context to other components in the system simply by passing the business object.

For clarification a business object in this scenario would be an object that performs operations against the entity model and LINQ to SQL. LINQ to SQL provides the entity/data access layer while the business object provides the application logical layer. In addition a business object would also provide more high level features like Load/Delete/Save/NewEntity/Validate etc. functionality that doesn't require actual access to the LINQ model directly - the business objects would handle all the data manipulation.

I've been using this approach as part of my Business Object wrapper around LINQ to SQL for some time and it works very well. You do potentially end up with multiple DataContext instances (one for each business object) but the number is typically small  (ie. 1 to 3 at a time typically). Overhead for creating a DataContext is not nill, but in my experience it's not enough to worry with small numbers of instances created per request.

The real advantage for me is the fact that I don't have to worry about the data context lifetime. I create my business objects on the application level, call a method and it internally manages creating the instance making the calls, managing change state and updates and then I can simply get rid of the object and be done. No worries about lifetime beyond the business object lifetime. In addition the business object provides an easier way yet to consistently handle basic CRUD operations without having to write LINQ syntax.

This approach can also be combined with the Thread specific approach in the last bullet. Rather than explicitly creating a data context you could decide if your object could be shared amongst many operations and in that case could be loaded from the thread context rather than creating a new instance each time.

DataContext and Threading

One thing I was wondering about today was how DataContext would work if you access a DataContext across threads - for example for an asynchronous operation in an ASP.NET. It turns out that this actually works fine (although I don't think it's thread safe for simultaneous access from multiple threads simultaneously.

The reason I was worried about this is that a few months back I'd been looking at Visual WebGui and it didn't work well in its semi-stateful mode of persisting a DataContext across requests. Basically what happened with VIsual WebGui is that loading the page and then later accessing the same DataContext would break apparently of the way that the threading and reconnection of the state for callbacks works.

To test I ran a kind of a silly test in an ASP.NET page to simulate a disconnected operation. It's totally faked up with a short wait operation to let the thread operation complete. Obviously this is not a practical approach for anything async - using AsycnTasks is a much better choice for any disconnected operations.

public partial class ThreadContext : System.Web.UI.Page
{
    TimeTrakkerContext Context = new TimeTrakkerContext();
    IQueryable<CustomerEntity> CustomerList;
    CustomerEntity Customer;
 
    protected void Page_Load(object sender, EventArgs e)
    {
        CustomerList =
            from c in Context.CustomerEntities
            where c.Company.StartsWith("West")
            select c;
 
        this.Customer = CustomerList.First();
 
        Response.Write("Original Values:<br>" + this.Customer.Company + " " + this.Customer.Address + " " + Thread.CurrentThread.ManagedThreadId.ToString());
 
        this.Customer.Company = "West Wind Technologies " + DateTime.Now.ToLongTimeString(); 
 
        Thread thread = new Thread(new ThreadStart(this.AccessDataContextOnThread));
        thread.Start();
 
        Thread.Sleep(2000);
    }
 
    public void AccessDataContextOnThread()
    {
        this.Customer.Address = "33 Kaiea Place " + DateTime.Now.ToLongTimeString();
        this.Context.SubmitChanges();
 
        Response.Write("<hr>From Thread:<br>" + this.Customer.Company + " " + this.Customer.Address + Thread.CurrentThread.ManagedThreadId.ToString());
 
    }
}

However it does demonstrate clearly that you can in fact access the DataContext across separate threads. For asynchronous scenarios in ASP.NET this should work well enough so you can do offloading with AsyncTasks or off to separate threads to continue processing after a request has completed or asynchronously while ASP.NET frees up an HttpApplication thread.

Even so DataContext works across threads, using it with multiple threads simultaneously surely would be disastrous, and wouldn't make much sense. One user updating while another is still editing would result in very undesirable operations indeed <s>... in any case DataContext is not thread safe anyway and all you'd accomplish is a hard crash eventually so avoid simultaneous multi-thread access.

In the end the key for DataContext change management is to ensure that the DataContext is always accessible and doesn't need to be recreated. As long as you can find some way to hang on to a single data context it can be used and be expected to correctly deal with change management.

Unfortunately as I pointed here and here , once you disconnect from the DataContext, the story with LINQ to SQL reconnecting and synching with another DataContext is bleak at best. So the best strategy is to keep hanging on to to the DataContext if you at all can <shrug>. Not always possible when you really need to cross machine boundaries with Web Services, but at least in that scenario you do get a fresh de-serialized instance of an object that can potentially be resynched by using Table.Attach().

For anything else it'll be better to implement something like one of the strategies above to hang on to your DataContext.

 

 

Thanks & Regards,

Arun Manglick || Senior Tech Lead