LinqDataSourceView.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / xsp / System / Web / Extensions / ui / webcontrols / LinqDataSourceView.cs / 1 / LinqDataSourceView.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.UI.WebControls { 
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Data.Linq; 
    using System.Data.Linq.Mapping;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization; 
    using System.Linq;
    using System.Reflection; 
    using System.Security.Permissions;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Web; 
    using System.Web.Compilation;
    using System.Web.Query.Dynamic; 
    using System.Web.Resources; 
    using DynamicValidatorEventArgs = System.Web.DynamicData.DynamicValidatorEventArgs;
    using DynamicDataSourceOperation = System.Web.DynamicData.DynamicDataSourceOperation; 

    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class LinqDataSourceView : DataSourceView, IStateManager { 

        private class LinqDataSourceAutoGeneratedWhere { 
            public LinqDataSourceAutoGeneratedWhere(string Where, IDictionary WhereParameters) { 
                this.Where = Where;
                this.WhereParameters = WhereParameters; 
            }
            public string Where { get; set; }
            public IDictionary WhereParameters;
        } 

        // This regular expression verifies that parameter names are set to valid identifiers.  This validation 
        // needs to match the parser's identifier validation as done in the default block of NextToken(). 
        private static readonly string _identifierPattern =
            @"^\s*[\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}_]" +                           // first character 
            @"[\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Nd}\p{Pc}\p{Mn}\p{Mc}\p{Cf}_]*"; // remaining characters

        private static readonly Regex _identifierRegex = new Regex(_identifierPattern + @"\s*$");
 
        private static readonly Regex _autoGenerateOrderByRegex = new Regex(_identifierPattern +
            @"(\s+(asc|ascending|desc|descending))?\s*$", RegexOptions.IgnoreCase);     // order operators 
 
        private static readonly object EventContextCreated = new object();
        private static readonly object EventContextCreating = new object(); 
        private static readonly object EventContextDisposing = new object();
        private static readonly object EventDeleted = new object();
        private static readonly object EventDeleting = new object();
        private static readonly object EventException = new object(); 
        private static readonly object EventInserted = new object();
        private static readonly object EventInserting = new object(); 
        private static readonly object EventSelected = new object(); 
        private static readonly object EventSelecting = new object();
        private static readonly object EventUpdated = new object(); 
        private static readonly object EventUpdating = new object();

        private HttpContext _context;
        private LinqDataSource _owner; 
        private bool _tracking;
 
        private bool _autoGenerateOrderByClause = false; 
        private bool _autoGenerateWhereClause = false;
        private bool _autoPage = true; 
        private bool _autoSort = true;
        private string _contextTypeName;
        private Type _contextType;
        private List _selectContexts; 
        private ParameterCollection _deleteParameters;
        private IDynamicQueryable _dynamicQueryable; 
        private bool _enableDelete = false; 
        private bool _enableInsert = false;
        private bool _enableObjectTracking = true; 
        private bool _enableUpdate = false;
        private string _groupBy;
        private ParameterCollection _groupByParameters;
        private ParameterCollection _insertParameters; 
        private ILinqToSql _linqToSql;
        private string _orderBy; 
        private ParameterCollection _orderByParameters; 
        private string _orderGroupsBy;
        private ParameterCollection _orderGroupsByParameters; 
        // using Hashtable for original values so that ObjectStateFormatter will serialize it properly in ViewState.
        private Hashtable _originalValues;
        private bool _reuseSelectContext;
        private string _selectNew; 
        private ParameterCollection _selectNewParameters;
        private bool _storeOriginalValuesInViewState = true; 
        private string _tableName; 
        private ParameterCollection _updateParameters;
        private string _where; 
        private ParameterCollection _whereParameters;

        public LinqDataSourceView(LinqDataSource owner, string name, HttpContext context)
            : this(owner, name, context, new DynamicQueryableWrapper(), new LinqToSqlWrapper()) { 
        }
 
        // internal constructor that takes mocks for unit tests. 
        internal LinqDataSourceView(LinqDataSource owner, string name, HttpContext context,
                                    IDynamicQueryable dynamicQueryable, ILinqToSql linqToSql) : base(owner, name) { 
            _owner = owner;
            _context = context;
            _dynamicQueryable = dynamicQueryable;
            _linqToSql = linqToSql; 
        }
 
        public bool AutoGenerateOrderByClause { 
            get {
                return _autoGenerateOrderByClause; 
            }
            set {
                if (_autoGenerateOrderByClause != value) {
                    _autoGenerateOrderByClause = value; 
                    OnDataSourceViewChanged(EventArgs.Empty);
                } 
            } 
        }
 
        public bool AutoGenerateWhereClause {
            get {
                return _autoGenerateWhereClause;
            } 
            set {
                if (_autoGenerateWhereClause != value) { 
                    _autoGenerateWhereClause = value; 
                    OnDataSourceViewChanged(EventArgs.Empty);
                } 
            }
        }

        public bool AutoPage { 
            get {
                return _autoPage; 
            } 
            set {
                if (_autoPage != value) { 
                    _autoPage = value;
                    OnDataSourceViewChanged(EventArgs.Empty);
                }
            } 
        }
 
        public bool AutoSort { 
            get {
                return _autoSort; 
            }
            set {
                if (_autoSort != value) {
                    _autoSort = value; 
                    OnDataSourceViewChanged(EventArgs.Empty);
                } 
            } 
        }
 
        public override bool CanDelete {
            get {
                return EnableDelete;
            } 
        }
 
        public override bool CanInsert { 
            get {
                return EnableInsert; 
            }
        }

        // When AutoPage is false the user should manually page in the Selecting event. 
        public override bool CanPage {
            get { 
                return true; 
            }
        } 

        // When AutoPage is false the user must set the total row count in the Selecting event.
        public override bool CanRetrieveTotalRowCount {
            get { 
                return true;
            } 
        } 

        // When AutoSort is false the user should manually sort in the Selecting event. 
        public override bool CanSort {
            get {
                return true;
            } 
        }
 
        public override bool CanUpdate { 
            get {
                return EnableUpdate; 
            }
        }

        protected internal virtual Type ContextType { 
            get {
                if (_contextType == null) { 
                    string typeName = ContextTypeName; 
                    if (String.IsNullOrEmpty(typeName)) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_ContextTypeNameNotSpecified, _owner.ID));
                    }
                    try {
                        _contextType = BuildManager.GetType(typeName, /*throwOnFail*/true, /*ignoreCase*/true); 
                    }
                    catch (Exception e) { 
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_ContextTypeNameNotFound, _owner.ID), e);
                    } 
                }
                return _contextType;
            }
        } 

        public virtual string ContextTypeName { 
            get { 
                return _contextTypeName ?? String.Empty;
            } 
            set {
                if (_contextTypeName != value) {
                    if (_reuseSelectContext) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_ContextTypeNameChanged, _owner.ID));
                    } 
                    _contextTypeName = value; 
                    _contextType = null;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            }
        }
 
        public ParameterCollection DeleteParameters {
            get { 
                if (_deleteParameters == null) { 
                    _deleteParameters = new ParameterCollection();
                } 
                return _deleteParameters;
            }
        }
 
        public bool EnableDelete {
            get { 
                return _enableDelete; 
            }
            set { 
                if (_enableDelete != value) {
                    _enableDelete = value;
                    OnDataSourceViewChanged(EventArgs.Empty);
                } 
            }
        } 
 
        public bool EnableInsert {
            get { 
                return _enableInsert;
            }
            set {
                if (_enableInsert != value) { 
                    _enableInsert = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                } 
            }
        } 

        public bool EnableObjectTracking {
            get {
                return _enableObjectTracking; 
            }
            set { 
                if (_enableObjectTracking != value) { 
                    if (_reuseSelectContext) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_EnableObjectTrackingChanged, _owner.ID));
                    }
                    _enableObjectTracking = value;
                } 
            }
        } 
 
        public bool EnableUpdate {
            get { 
                return _enableUpdate;
            }
            set {
                if (_enableUpdate != value) { 
                    _enableUpdate = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                } 
            }
        } 

        public string GroupBy {
            get {
                return _groupBy ?? String.Empty; 
            }
            set { 
                if (_groupBy != value) { 
                    _groupBy = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            }
        }
 
        public ParameterCollection GroupByParameters {
            get { 
                if (_groupByParameters == null) { 
                    _groupByParameters = new ParameterCollection();
                    _groupByParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler); 
                    if (_tracking) {
                        ((IStateManager)_groupByParameters).TrackViewState();
                    }
                } 
                return _groupByParameters;
            } 
        } 

        public ParameterCollection InsertParameters { 
            get {
                if (_insertParameters == null) {
                    _insertParameters = new ParameterCollection();
                } 
                return _insertParameters;
            } 
        } 

        protected bool IsTrackingViewState { 
            get {
                return _tracking;
            }
        } 

        public string OrderBy { 
            get { 
                return _orderBy ?? String.Empty;
            } 
            set {
                if (_orderBy != value) {
                    _orderBy = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            } 
        } 

        public ParameterCollection OrderByParameters { 
            get {
                if (_orderByParameters == null) {
                    _orderByParameters = new ParameterCollection();
                    _orderByParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler); 
                    if (_tracking) {
                        ((IStateManager)_orderByParameters).TrackViewState(); 
                    } 
                }
                return _orderByParameters; 
            }
        }

        public string OrderGroupsBy { 
            get {
                return _orderGroupsBy ?? String.Empty; 
            } 
            set {
                if (_orderGroupsBy != value) { 
                    _orderGroupsBy = value;
                    OnDataSourceViewChanged(EventArgs.Empty);
                }
            } 
        }
 
        public ParameterCollection OrderGroupsByParameters { 
            get {
                if (_orderGroupsByParameters == null) { 
                    _orderGroupsByParameters = new ParameterCollection();
                    _orderGroupsByParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler);
                    if (_tracking) {
                        ((IStateManager)_orderGroupsByParameters).TrackViewState(); 
                    }
                } 
                return _orderGroupsByParameters; 
            }
        } 

        [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix",
            Justification = "Removing 'New' would conflict with the Select() method.")]
        public string SelectNew { 
            get {
                return _selectNew ?? String.Empty; 
            } 
            set {
                if (_selectNew != value) { 
                    _selectNew = value;
                    OnDataSourceViewChanged(EventArgs.Empty);
                }
            } 
        }
 
        public ParameterCollection SelectNewParameters { 
            get {
                if (_selectNewParameters == null) { 
                    _selectNewParameters = new ParameterCollection();
                    _selectNewParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler);
                    if (_tracking) {
                        ((IStateManager)_selectNewParameters).TrackViewState(); 
                    }
                } 
                return _selectNewParameters; 
            }
        } 

        public bool StoreOriginalValuesInViewState {
            get {
                return _storeOriginalValuesInViewState; 
            }
            set { 
                if (_storeOriginalValuesInViewState != value) { 
                    _storeOriginalValuesInViewState = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            }
        }
 
        public string TableName {
            get { 
                return _tableName ?? String.Empty; 
            }
            set { 
                if (_tableName != value) {
                    if (_reuseSelectContext) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                            AtlasWeb.LinqDataSourceView_TableNameChanged, _owner.ID)); 
                    }
                    _tableName = value; 
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            } 
        }

        public ParameterCollection UpdateParameters {
            get { 
                if (_updateParameters == null) {
                    _updateParameters = new ParameterCollection(); 
                } 
                return _updateParameters;
            } 
        }

        public string Where {
            get { 
                return _where ?? String.Empty;
            } 
            set { 
                if (_where != value) {
                    _where = value; 
                    OnDataSourceViewChanged(EventArgs.Empty);
                }
            }
        } 

        public ParameterCollection WhereParameters { 
            get { 
                if (_whereParameters == null) {
                    _whereParameters = new ParameterCollection(); 
                    _whereParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler);
                    if (_tracking) {
                        ((IStateManager)_whereParameters).TrackViewState();
                    } 
                }
                return _whereParameters; 
            } 
        }
 
        public event EventHandler ContextCreated {
            add {
                Events.AddHandler(EventContextCreated, value);
            } 
            remove {
                Events.RemoveHandler(EventContextCreated, value); 
            } 
        }
 
        public event EventHandler ContextCreating {
            add {
                Events.AddHandler(EventContextCreating, value);
            } 
            remove {
                Events.RemoveHandler(EventContextCreating, value); 
            } 
        }
 
        public event EventHandler ContextDisposing {
            add {
                Events.AddHandler(EventContextDisposing, value);
            } 
            remove {
                Events.RemoveHandler(EventContextDisposing, value); 
            } 
        }
 
        public event EventHandler Deleted {
            add {
                Events.AddHandler(EventDeleted, value);
            } 
            remove {
                Events.RemoveHandler(EventDeleted, value); 
            } 
        }
 
        public event EventHandler Deleting {
            add {
                Events.AddHandler(EventDeleting, value);
            } 
            remove {
                Events.RemoveHandler(EventDeleting, value); 
            } 
        }
 
        internal event EventHandler Exception {
            add {
                Events.AddHandler(EventException, value);
            } 
            remove {
                Events.RemoveHandler(EventException, value); 
            } 
        }
 
        public event EventHandler Inserted {
            add {
                Events.AddHandler(EventInserted, value);
            } 
            remove {
                Events.RemoveHandler(EventInserted, value); 
            } 
        }
 
        public event EventHandler Inserting {
            add {
                Events.AddHandler(EventInserting, value);
            } 
            remove {
                Events.RemoveHandler(EventInserting, value); 
            } 
        }
 
        public event EventHandler Selected {
            add {
                Events.AddHandler(EventSelected, value);
            } 
            remove {
                Events.RemoveHandler(EventSelected, value); 
            } 
        }
 
        public event EventHandler Selecting {
            add {
                Events.AddHandler(EventSelecting, value);
            } 
            remove {
                Events.RemoveHandler(EventSelecting, value); 
            } 
        }
 
        public event EventHandler Updated {
            add {
                Events.AddHandler(EventUpdated, value);
            } 
            remove {
                Events.RemoveHandler(EventUpdated, value); 
            } 
        }
 
        public event EventHandler Updating {
            add {
                Events.AddHandler(EventUpdating, value);
            } 
            remove {
                Events.RemoveHandler(EventUpdating, value); 
            } 
        }
 
        private static IQueryable AsQueryable(object o) {
            IQueryable oQueryable = o as IQueryable;
            if (oQueryable != null) {
                return oQueryable; 
            }
 
            // Wrap strings in IEnumerable instead of treating as IEnumerable. 
            string oString = o as string;
            if (oString != null) { 
                return Queryable.AsQueryable(new string[] { oString });
            }

            IEnumerable oEnumerable = o as IEnumerable; 
            if (oEnumerable != null) {
                // IEnumerable can be directly converted to an IQueryable. 
                Type genericType = LinqDataSourceHelper.FindGenericEnumerableType(o.GetType()); 
                if (genericType != null) {
                    // The non-generic Queryable.AsQueryable gets called for array types, executing 
                    // the FindGenericType logic again.  Might want to investigate way to avoid this.
                    return Queryable.AsQueryable(oEnumerable);
                }
                // Wrap non-generic IEnumerables in IEnumerable. 
                List genericList = new List();
                foreach (object item in oEnumerable) { 
                    genericList.Add(item); 
                }
                return Queryable.AsQueryable(genericList); 
            }

            // Wrap non-IEnumerable types in IEnumerable.
            Type listType = typeof(List<>).MakeGenericType(o.GetType()); 
            IList list = (IList)CreateObjectInstance(listType);
            list.Add(o); 
            return Queryable.AsQueryable(list); 
        }
 
        private object BuildDataObject(Type dataObjectType, IDictionary inputParameters) {
            object dataObject = CreateObjectInstance(dataObjectType);

            Dictionary convertOrValidateExceptions = null; 
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(dataObject);
            foreach (DictionaryEntry de in inputParameters) { 
                string propName = (de.Key == null ? String.Empty : de.Key.ToString()); 
                PropertyDescriptor property = props.Find(propName, /*ignoreCase*/true);
                // NOTE: No longer throws when a property is not found or is read only.  This makes 
                // Delete, Insert and Update operations more optimistic, allowing scenarios such as:
                // 1) Deletes and Updates after projecting data in the Selecting event.
                // 2) Deletes and Updates after selecting children of the data object type in the
                //    Selecting event. 
                if ((property != null) && (!property.IsReadOnly)) {
                    try { 
                        object value = BuildObjectValue(de.Value, property.PropertyType, propName); 
                        property.SetValue(dataObject, value);
                    } 
                    catch (Exception e) {
                        if (convertOrValidateExceptions == null) {
                            convertOrValidateExceptions = new Dictionary(
                                StringComparer.OrdinalIgnoreCase); 
                        }
                        convertOrValidateExceptions[property.Name] = e; 
                    } 
                }
            } 

            // package up conversion or dlinq validation exceptions into single exception.
            if (convertOrValidateExceptions != null) {
                // Include the text of the first exception as part of the full exception, 
                // to make it less cryptic in scenarios where it gets shown.
                throw new LinqDataSourceValidationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_ValidationFailed, dataObjectType, convertOrValidateExceptions.Values.First().Message), 
                    convertOrValidateExceptions);
            } 

            return dataObject;
        }
 
        private LinqDataSourceEditData BuildDeleteDataObject(object table, IDictionary keys, IDictionary oldValues) {
            Type dataObjectType = GetDataObjectType(table.GetType()); 
            IDictionary caseInsensitiveOldValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); 
            IDictionary originalValues = GetOriginalValues(keys);
 
            ParameterCollection deleteParameters = DeleteParameters;
            MergeDictionaries(dataObjectType, deleteParameters, keys, caseInsensitiveOldValues);
            MergeDictionaries(dataObjectType, deleteParameters, oldValues, caseInsensitiveOldValues);
            if (originalValues != null) { 
                MergeDictionaries(dataObjectType, deleteParameters, originalValues, caseInsensitiveOldValues);
            } 
 
            LinqDataSourceEditData editData = new LinqDataSourceEditData();
            editData.OriginalDataObject = BuildDataObject(dataObjectType, caseInsensitiveOldValues); 
            return editData;
        }

        private LinqDataSourceEditData BuildInsertDataObject(object table, IDictionary values) { 
            Type dataObjectType = GetDataObjectType(table.GetType());
            IDictionary caseInsensitiveNewValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); 
            MergeDictionaries(dataObjectType, InsertParameters, InsertParameters.GetValues(_context, _owner), 
                caseInsensitiveNewValues);
            MergeDictionaries(dataObjectType, InsertParameters, values, caseInsensitiveNewValues); 

            LinqDataSourceEditData editData = new LinqDataSourceEditData();
            editData.NewDataObject = BuildDataObject(dataObjectType, caseInsensitiveNewValues);
            return editData; 
        }
 
        internal static object BuildObjectValue(object value, Type destinationType, string paramName) { 
            // NOTE: This method came from ObjectDataSource with no changes made.
            // Only consider converting the type if the value is non-null and the types don't match 
            if ((value != null) && (!destinationType.IsInstanceOfType(value))) {
                Type innerDestinationType = destinationType;
                bool isNullable = false;
                if (destinationType.IsGenericType && 
                    (destinationType.GetGenericTypeDefinition() == typeof(Nullable<>))) {
                    innerDestinationType = destinationType.GetGenericArguments()[0]; 
                    isNullable = true; 
                }
                else { 
                    if (destinationType.IsByRef) {
                        innerDestinationType = destinationType.GetElementType();
                    }
                } 

                // Try to convert from for example string to DateTime, so that 
                // afterwards we can convert DateTime to Nullable 

                // If the value is a string, we attempt to use a TypeConverter to convert it 
                value = ConvertType(value, innerDestinationType, paramName);

                // Special-case the value when the destination is Nullable
                if (isNullable) { 
                    Type paramValueType = value.GetType();
                    if (innerDestinationType != paramValueType) { 
                        // Throw if for example, we are trying to convert from int to Nullable 
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                            AtlasWeb.LinqDataSourceView_CannotConvertType, paramName, paramValueType.FullName, 
                            String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>",
                            destinationType.GetGenericArguments()[0].FullName)));
                    }
                } 
            }
            return value; 
        } 

        private LinqDataSourceEditData BuildUpdateDataObjects(object table, IDictionary keys, 
                                                              IDictionary values, IDictionary oldValues) {
            Type dataObjectType = GetDataObjectType(table.GetType());
            IDictionary caseInsensitiveNewValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase);
            IDictionary caseInsensitiveOldValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); 
            IDictionary originalValues = GetOriginalValues(keys);
 
            // We start out with the old values, just to pre-populate the list with items 
            // that might not have corresponding new values. For example if a GridView has
            // a read-only field, there will be an old value, but no new value. The data object 
            // still has to have *some* value for a given field, so we just use the old value.
            ParameterCollection updateParameters = UpdateParameters;
            MergeDictionaries(dataObjectType, updateParameters, oldValues, caseInsensitiveOldValues, caseInsensitiveNewValues);
            MergeDictionaries(dataObjectType, updateParameters, keys, caseInsensitiveOldValues, caseInsensitiveNewValues); 
            if (originalValues != null) {
                MergeDictionaries(dataObjectType, updateParameters, originalValues, caseInsensitiveOldValues, caseInsensitiveNewValues); 
            } 
            MergeDictionaries(dataObjectType, updateParameters, values, caseInsensitiveNewValues);
 
            LinqDataSourceEditData editData = new LinqDataSourceEditData();
            editData.NewDataObject = BuildDataObject(dataObjectType, caseInsensitiveNewValues);
            editData.OriginalDataObject = BuildDataObject(dataObjectType, caseInsensitiveOldValues);
            return editData; 
        }
 
        private static object ConvertType(object value, Type type, string paramName) { 
            // NOTE: This method came from ObjectDataSource with no changes made.
            string s = value as string; 
            if (s != null) {
                // Get the type converter for the destination type
                TypeConverter converter = TypeDescriptor.GetConverter(type);
                if (converter != null) { 
                    // Perform the conversion
                    try { 
                        value = converter.ConvertFromString(s); 
                    }
                    catch (NotSupportedException) { 
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                            AtlasWeb.LinqDataSourceView_CannotConvertType, paramName, typeof(string).FullName,
                            type.FullName));
                    } 
                    catch (FormatException) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_CannotConvertType, paramName, typeof(string).FullName, 
                            type.FullName));
                    } 
                }
            }
            return value;
        } 

        protected virtual object CreateContext(Type contextType) { 
            return CreateObjectInstance(contextType); 
        }
 
        private LinqDataSourceContextData CreateContextAndTable(DataSourceOperation operation) {
            LinqDataSourceContextData contextData = null;
            bool eventFired = false;
            try { 
                LinqDataSourceContextEventArgs contextEventArgs = new LinqDataSourceContextEventArgs(operation);
                OnContextCreating(contextEventArgs); 
 
                contextData = new LinqDataSourceContextData(contextEventArgs.ObjectInstance);
                Type contextType = null; 
                MemberInfo tableMemberInfo = null;
                if (contextData.Context == null) {
                    // construct the context unless accessing a static table for Select.
                    contextType = ContextType; 
                    tableMemberInfo = GetTableMemberInfo(contextType);
                    if (tableMemberInfo != null) { 
                        if (MemberIsStatic(tableMemberInfo)) { 
                            if (operation != DataSourceOperation.Select) {
                                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                                    AtlasWeb.LinqDataSourceView_TableCannotBeStatic, TableName, contextType.Name, _owner.ID));
                            }
                        }
                        else { 
                            contextData.Context = CreateContext(contextType);
                            contextData.IsNewContext = true; 
                        } 
                    }
                } 
                else {
                    // use the manually constructed context.
                    tableMemberInfo = GetTableMemberInfo(contextData.Context.GetType());
                } 

                // fetch the table from the context. 
                if (tableMemberInfo != null) { 
                    FieldInfo field = tableMemberInfo as FieldInfo;
                    if (field != null) { 
                        contextData.Table = field.GetValue(contextData.Context);
                    }
                    PropertyInfo property = tableMemberInfo as PropertyInfo;
                    if (property != null) { 
                        contextData.Table = property.GetValue(contextData.Context, null);
                    } 
                } 
                if (contextData.Table == null) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_TableNameNotFound, TableName, contextType.Name, _owner.ID));
                }
            }
            catch (Exception e) { 
                eventFired = true;
                LinqDataSourceStatusEventArgs createdEventArgs = new LinqDataSourceStatusEventArgs(e); 
                OnContextCreated(createdEventArgs); 
                OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.ContextCreate));
                // CreateContextAndTable will return null if this exception is handled. 
                if (!createdEventArgs.ExceptionHandled) {
                    throw;
                }
            } 
            finally {
                if (!eventFired) { 
                    // contextData can be null if exception thrown from ContextCreating handler. 
                    object context = (contextData == null) ? null : contextData.Context;
                    LinqDataSourceStatusEventArgs createdEventArgs = new LinqDataSourceStatusEventArgs(context); 
                    OnContextCreated(createdEventArgs);
                }
            }
            return contextData; 
        }
 
        private LinqDataSourceContextData CreateContextAndTableForEdit(DataSourceOperation operation) { 
            LinqDataSourceContextData contextData = CreateContextAndTable(operation);
            // context data may be null or incomplete if an exception was handled 
            if (contextData != null) {
                if (contextData.Context == null) {
                    return null;
                } 
                if (contextData.Table == null) {
                    ReleaseContext(contextData.Context); 
                    return null; 
                }
                ValidateContextType(contextData.Context.GetType(), false); 
                ValidateTableType(contextData.Table.GetType(), false);
            }
            return contextData;
        } 

        private LinqDataSourceContextData CreateContextAndTableForSelect() { 
            if (_selectContexts == null) { 
                _selectContexts = new List();
            } 
            else if (_reuseSelectContext && _selectContexts.Count > 0) {
                return _selectContexts[_selectContexts.Count - 1];
            }
 
            // context data may be null if an exception was handled
            LinqDataSourceContextData contextData = CreateContextAndTable(DataSourceOperation.Select); 
            if (contextData != null) { 
                if (contextData.Context != null) {
                     ValidateContextType(contextData.Context.GetType(), true); 
                }
                if (contextData.Table != null) {
                     ValidateTableType(contextData.Table.GetType(), true);
                } 

                _selectContexts.Add(contextData); 
 
                // context may not be dlinq context or may be null if table was static.
                DataContext dlinqContext = contextData.Context as DataContext; 
                if ((dlinqContext != null) && contextData.IsNewContext) {
                    dlinqContext.ObjectTrackingEnabled = EnableObjectTracking;
                }
                // don't reuse dlinq contexts that cache data or exterior changes will not be reflected. 
                _reuseSelectContext = (dlinqContext == null) || !EnableObjectTracking;
            } 
            return contextData; 
        }
 
        private static object CreateObjectInstance(Type type) {
            // FastCreatePublicInstance is faster than Activator.CreateInstance since it caches the type factories.
            return HttpRuntime.FastCreatePublicInstance(type);
        } 

        public int Delete(IDictionary keys, IDictionary oldValues) { 
            return ExecuteDelete(keys, oldValues); 
        }
 
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object",
            Justification = "Names are consistent with those used in the ObjectDataSource classes")]
        protected virtual void DeleteDataObject(object dataContext, object table, object oldDataObject) {
            _linqToSql.Attach((ITable)table, oldDataObject); 
            _linqToSql.Remove((ITable)table, oldDataObject);
            _linqToSql.SubmitChanges((DataContext)dataContext); 
        } 

        private IDictionary EscapeParameterKeys(IDictionary parameters) { 
            Dictionary escapedParameters = new Dictionary(parameters.Count,
                StringComparer.OrdinalIgnoreCase);
            foreach (KeyValuePair parameter in parameters) {
                string key = parameter.Key; 
                if (String.IsNullOrEmpty(key)) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_ParametersMustBeNamed, _owner.ID)); 
                }
                ValidateParameterName(key); 
                escapedParameters.Add('@' + key, parameter.Value);
            }
            return escapedParameters;
        } 

        protected override int ExecuteDelete(IDictionary keys, IDictionary oldValues) { 
            ValidateDeleteSupported(keys, oldValues); 
            LinqDataSourceContextData contextData = null;
            try { 
                contextData = CreateContextAndTableForEdit(DataSourceOperation.Delete);
                if (contextData != null) {
                    LinqDataSourceEditData editData = null;
                    LinqDataSourceDeleteEventArgs deleteEventArgs = null; 
                    try {
                        editData = BuildDeleteDataObject(contextData.Table, keys, oldValues); 
                    } 
                    catch (LinqDataSourceValidationException e) {
                        // allow user to handle conversion or dlinq property validation exceptions. 
                        deleteEventArgs = new LinqDataSourceDeleteEventArgs(e);
                        OnDeleting(deleteEventArgs);
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Delete));
                        if (deleteEventArgs.ExceptionHandled) { 
                            return -1;
                        } 
                        throw; 
                    }
                    deleteEventArgs = new LinqDataSourceDeleteEventArgs(editData.OriginalDataObject); 
                    OnDeleting(deleteEventArgs);
                    if (deleteEventArgs.Cancel) {
                        return -1;
                    } 

                    LinqDataSourceStatusEventArgs deletedEventArgs = null; 
                    try { 
                        DeleteDataObject(contextData.Context, contextData.Table, deleteEventArgs.OriginalObject);
                    } 
                    catch (Exception e) {
                        // allow user to handle dlinq exceptions including OnValidate validation.
                        deletedEventArgs = new LinqDataSourceStatusEventArgs(e);
                        OnDeleted(deletedEventArgs); 
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Delete));
                        if (deletedEventArgs.ExceptionHandled) { 
                            return -1; 
                        }
                        throw; 
                    }
                    deletedEventArgs = new LinqDataSourceStatusEventArgs(deleteEventArgs.OriginalObject);
                    OnDeleted(deletedEventArgs);
                } 
            }
            finally { 
                if (contextData != null) { 
                    ReleaseContext(contextData.Context);
                } 
            }
            // estimated number of rows deleted.
            return 1;
        } 

        protected override int ExecuteInsert(IDictionary values) { 
            ValidateInsertSupported(values); 
            LinqDataSourceContextData contextData = null;
            try { 
                contextData = CreateContextAndTableForEdit(DataSourceOperation.Insert);
                if (contextData != null) {
                    LinqDataSourceEditData editData = null;
                    LinqDataSourceInsertEventArgs insertEventArgs = null; 
                    try {
                        editData = BuildInsertDataObject(contextData.Table, values); 
                    } 
                    catch (LinqDataSourceValidationException e) {
                        // allow user to handle conversion or dlinq property validation exceptions. 
                        insertEventArgs = new LinqDataSourceInsertEventArgs(e);
                        OnInserting(insertEventArgs);
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Insert));
                        if (insertEventArgs.ExceptionHandled) { 
                            return -1;
                        } 
                        throw; 
                    }
                    insertEventArgs = new LinqDataSourceInsertEventArgs(editData.NewDataObject); 
                    OnInserting(insertEventArgs);
                    if (insertEventArgs.Cancel) {
                        return -1;
                    } 

                    LinqDataSourceStatusEventArgs insertedEventArgs = null; 
                    try { 
                        InsertDataObject(contextData.Context, contextData.Table, insertEventArgs.NewObject);
                    } 
                    catch (Exception e) {
                        // allow user to handle dlinq exceptions including OnValidate validation.
                        insertedEventArgs = new LinqDataSourceStatusEventArgs(e);
                        OnInserted(insertedEventArgs); 
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Insert));
                        if (insertedEventArgs.ExceptionHandled) { 
                            return -1; 
                        }
                        throw; 
                    }
                    insertedEventArgs = new LinqDataSourceStatusEventArgs(insertEventArgs.NewObject);
                    OnInserted(insertedEventArgs);
                } 
            }
            finally { 
                if (contextData != null) { 
                    ReleaseContext(contextData.Context);
                } 
            }
            // estimated number of rows inserted.
            return 1;
        } 

        protected internal override IEnumerable ExecuteSelect(DataSourceSelectArguments arguments) { 
            if (arguments == null) { 
                throw new ArgumentNullException("arguments");
            } 

            _originalValues = null;
            IDictionary whereParameters = GetParameterValues(WhereParameters);
            IOrderedDictionary orderByParameters = GetOrderedParameterValues(OrderByParameters); 
            IDictionary groupByParameters = GetParameterValues(GroupByParameters);
            IDictionary orderGroupsByParameters = GetParameterValues(OrderGroupsByParameters); 
            IDictionary selectNewParameters = GetParameterValues(SelectNewParameters); 

            LinqDataSourceSelectEventArgs selectEventArgs = new LinqDataSourceSelectEventArgs(arguments, 
                whereParameters, orderByParameters, groupByParameters, orderGroupsByParameters, selectNewParameters);
            OnSelecting(selectEventArgs);
            if (selectEventArgs.Cancel) {
                return null; 
            }
 
            object selectResult = selectEventArgs.Result; 
            object table = selectResult;
 
            // Original values should only be stored for valid delete and update scenarios.
            bool storeOriginalValues = StoreOriginalValuesInViewState && (CanDelete || CanUpdate) &&
                String.IsNullOrEmpty(GroupBy) && String.IsNullOrEmpty(SelectNew);
 
            if (selectResult == null) {
                LinqDataSourceContextData contextData = CreateContextAndTableForSelect(); 
                if (contextData != null) { 
                    selectResult = contextData.Table;
                    table = contextData.Table; 
                }
            }
            // If the provided select result was not a DLinq table and we need to store
            // original values then we must get the table and create a new data context 
            // instance so that we can access the column metadata.
            else if (!(table is ITable) && storeOriginalValues) { 
                LinqDataSourceContextData contextData = CreateContextAndTableForSelect(); 
                if (contextData != null) {
                    table = contextData.Table; 
                }
            }

            return ExecuteSelectQuery(selectEventArgs, selectResult, table, storeOriginalValues); 
        }
 
        private IQueryable ExecuteSelectAutoSortAndPage(IQueryable source, DataSourceSelectArguments arguments) { 
            IQueryable result = source;
            string sortExpression = arguments.SortExpression; 
            if (AutoSort && (!String.IsNullOrEmpty(sortExpression))) {
                result = _dynamicQueryable.OrderBy(result, sortExpression);
            }
            if (AutoPage) { 
                if (arguments.RetrieveTotalRowCount) {
                    arguments.TotalRowCount = _dynamicQueryable.Count(result); 
                } 
                if ((arguments.MaximumRows > 0) && (arguments.StartRowIndex >= 0)) {
                    result = _dynamicQueryable.Skip(result, arguments.StartRowIndex); 
                    result = _dynamicQueryable.Take(result, arguments.MaximumRows);
                }
            }
            else if (arguments.RetrieveTotalRowCount && (arguments.TotalRowCount == -1)) { 
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                    AtlasWeb.LinqDataSourceView_PagingNotHandled, _owner.ID)); 
            } 
            return result;
        } 

        private IQueryable ExecuteSelectExpressions(IQueryable source, IDictionary whereValues,
                                                    IOrderedDictionary orderByOrderedValues,
                                                    IDictionary groupByValues, 
                                                    IDictionary orderGroupsByValues,
                                                    IDictionary selectNewValues) { 
            IQueryable result = source; 
            string where = Where;
            if (AutoGenerateWhereClause) { 
                if (!String.IsNullOrEmpty(where)) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                        AtlasWeb.LinqDataSourceView_WhereAlreadySpecified, _owner.ID));
                } 
                LinqDataSourceAutoGeneratedWhere generatedWhere = GenerateWhereClauseAndEscapeParameterKeys(whereValues);
                if (!String.IsNullOrEmpty(generatedWhere.Where)) { 
                    result = _dynamicQueryable.Where(result, generatedWhere.Where, generatedWhere.WhereParameters); 
                }
            } 
            else if (!String.IsNullOrEmpty(where)) {
                result = _dynamicQueryable.Where(result, where, EscapeParameterKeys(whereValues));
            }
 
            string orderBy = OrderBy;
            IDictionary orderByValues = null; 
            if (AutoGenerateOrderByClause) { 
                if (!String.IsNullOrEmpty(orderBy)) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_OrderByAlreadySpecified, _owner.ID));
                }
                orderBy = GenerateOrderByClause(orderByOrderedValues);
                orderByValues = new Dictionary(0); 
            }
            else { 
                orderByValues = GetParameterValues(orderByOrderedValues); 
            }
            if (!String.IsNullOrEmpty(orderBy)) { 
                result = _dynamicQueryable.OrderBy(result, orderBy, EscapeParameterKeys(orderByValues));
            }

            string groupBy = GroupBy; 
            if (String.IsNullOrEmpty(groupBy)) {
                if (!String.IsNullOrEmpty(OrderGroupsBy)) { 
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_OrderGroupsByRequiresGroupBy, _owner.ID));
                } 
            }
            else {
                result = _dynamicQueryable.GroupBy(result, groupBy, "it", EscapeParameterKeys(groupByValues));
                string orderGroupsBy = OrderGroupsBy; 
                if (!String.IsNullOrEmpty(orderGroupsBy)) {
                    result = _dynamicQueryable.OrderBy(result, orderGroupsBy, EscapeParameterKeys(orderGroupsByValues)); 
                } 
            }
 
            string selectNew = SelectNew;
            if (!String.IsNullOrEmpty(selectNew)) {
                result = _dynamicQueryable.Select(result, selectNew, EscapeParameterKeys(selectNewValues));
            } 

            return result; 
        } 

        private IEnumerable ExecuteSelectQuery(LinqDataSourceSelectEventArgs selectEventArgs, object selectResult, 
                                               object table, bool storeOriginalValues) {
            IList result = null;
            if (selectResult != null) {
                try { 
                    IQueryable query = AsQueryable(selectResult);
                    query = ExecuteSelectExpressions(query, selectEventArgs.WhereParameters, 
                                                     selectEventArgs.OrderByParameters, 
                                                     selectEventArgs.GroupByParameters,
                                                     selectEventArgs.OrderGroupsByParameters, 
                                                     selectEventArgs.SelectParameters);
                    query = ExecuteSelectAutoSortAndPage(query, selectEventArgs.Arguments);

                    Type dataObjectType = GetDataObjectType(query.GetType()); 
                    result = ToList(query, dataObjectType);
 
                    if (storeOriginalValues) { 
                        ITable dlinqTable = table as ITable;
                        if ((dlinqTable != null) && dataObjectType.Equals(GetDataObjectType(dlinqTable.GetType()))) { 
                            StoreOriginalValues(dlinqTable, dataObjectType, result);
                        }
                    }
                } 
                catch (Exception e) {
                    result = null; 
                    LinqDataSourceStatusEventArgs selectedEventArgs = new LinqDataSourceStatusEventArgs(e); 
                    OnSelected(selectedEventArgs);
                    OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Select)); 
                    if (!selectedEventArgs.ExceptionHandled) {
                        throw;
                    }
                } 
                finally {
                    if (result != null) { 
                        int totalRowCount = -1; // paging performed, but row count not available. 
                        if (selectEventArgs.Arguments.RetrieveTotalRowCount) {
                            totalRowCount = selectEventArgs.Arguments.TotalRowCount; 
                        }
                        else if (!AutoPage) {
                            totalRowCount = result.Count;
                        } 
                        LinqDataSourceStatusEventArgs selectedEventArgs = new LinqDataSourceStatusEventArgs(result, totalRowCount);
                        OnSelected(selectedEventArgs); 
                    } 
                }
            } 
            return result;
        }

        protected override int ExecuteUpdate(IDictionary keys, IDictionary values, IDictionary oldValues) { 
            ValidateUpdateSupported(keys, values, oldValues);
            LinqDataSourceContextData contextData = null; 
            try { 
                contextData = CreateContextAndTableForEdit(DataSourceOperation.Update);
                if (contextData != null) { 
                    LinqDataSourceEditData editData = null;
                    LinqDataSourceUpdateEventArgs updateEventArgs = null;
                    try {
                        editData = BuildUpdateDataObjects(contextData.Table, keys, values, oldValues); 
                    }
                    catch (LinqDataSourceValidationException e) { 
                        // allow user to handle conversion or dlinq property validation exceptions. 
                        updateEventArgs = new LinqDataSourceUpdateEventArgs(e);
                        OnUpdating(updateEventArgs); 
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Update));
                        if (updateEventArgs.ExceptionHandled) {
                            return -1;
                        } 
                        throw;
                    } 
                    updateEventArgs = new LinqDataSourceUpdateEventArgs(editData.OriginalDataObject, editData.NewDataObject); 
                    OnUpdating(updateEventArgs);
                    if (updateEventArgs.Cancel) { 
                        return -1;
                    }

                    LinqDataSourceStatusEventArgs updatedEventArgs = null; 
                    try {
                        UpdateDataObject(contextData.Context, contextData.Table, updateEventArgs.OriginalObject, updateEventArgs.NewObject); 
                    } 
                    catch (Exception e) {
                        ResetDataObject(contextData.Table, updateEventArgs.OriginalObject); 
                        // allow user to handle dlinq exceptions including OnValidate validation.
                        updatedEventArgs = new LinqDataSourceStatusEventArgs(e);
                        OnUpdated(updatedEventArgs);
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Update)); 
                        if (updatedEventArgs.ExceptionHandled) {
                            return -1; 
                        } 
                        throw;
                    } 
                    updatedEventArgs = new LinqDataSourceStatusEventArgs(updateEventArgs.NewObject);
                    OnUpdated(updatedEventArgs);
                }
            } 
            finally {
                if (contextData != null) { 
                    ReleaseContext(contextData.Context); 
                }
            } 
            // estimated number of rows updated.
            return 1;
        }
 
        private string GenerateOrderByClause(IOrderedDictionary orderByParameters) {
            if ((orderByParameters != null) && (orderByParameters.Count > 0)) { 
                StringBuilder orderBy = new StringBuilder(); 
                foreach (DictionaryEntry parameter in orderByParameters) {
                    string value = (string)parameter.Value; 
                    // exclude null and empty values.
                    if (!String.IsNullOrEmpty(value)) {
                        string name = (string)parameter.Key;
                        ValidateOrderByParameter(name, value); 
                        if (orderBy.Length > 0) {
                            orderBy.Append(", "); 
                        } 
                        orderBy.Append(value);
                    } 
                }
                return orderBy.ToString();
            }
            return String.Empty; 
        }
 
        private LinqDataSourceAutoGeneratedWhere GenerateWhereClauseAndEscapeParameterKeys(IDictionary whereParameters) { 
            if ((whereParameters != null) && (whereParameters.Count > 0)) {
                Dictionary escapedParameters = new Dictionary(whereParameters.Count); 
                StringBuilder where = new StringBuilder();
                int index = 0;
                foreach (KeyValuePair parameter in whereParameters) {
                    string key = parameter.Key; 
                    string value = (parameter.Value == null) ? null : parameter.Value.ToString();
                    // exclude null and empty values. 
                    if (!(String.IsNullOrEmpty(key) || String.IsNullOrEmpty(value))) { 
                        string newKey = "@p" + index++;
                        if (where.Length > 0) { 
                            where.Append(" AND ");
                        }
                        where.Append(key);
                        where.Append(" == "); 
                        where.Append(newKey);
                        escapedParameters.Add(newKey, parameter.Value); 
                    } 
                }
                return new LinqDataSourceAutoGeneratedWhere(where.ToString(), escapedParameters); 
            }
            return new LinqDataSourceAutoGeneratedWhere(String.Empty, null);
        }
 
        protected virtual Type GetDataObjectType(Type tableType) {
            if (tableType.IsGenericType) { 
                Type[] genericTypes = tableType.GetGenericArguments(); 
                if (genericTypes.Length == 1) {
                    return genericTypes[0]; 
                }
            }
            return typeof(object);
        } 

        private IOrderedDictionary GetOrderedParameterValues(ParameterCollection parameters) { 
            IOrderedDictionary orderedValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); 
            IDictionary parameterValues = parameters.GetValues(_context, _owner);
            foreach (DictionaryEntry entry in parameterValues) { 
                orderedValues[entry.Key] = entry.Value;
            }
            return orderedValues;
        } 

        private IDictionary GetOriginalValues(IDictionary keys) { 
            // Table data is stored in a hashtable with column names for keys and an ArrayList of row data for values. 
            // i.e, Hashtable { ID = ArrayList { 0, 1, 2 }, Name = ArrayList { "A", "B", "C" } }
            if (_originalValues != null) { 
                // matches list keeps track of row indexes which match.
                List matches = new List();
                foreach (DictionaryEntry entry in keys) {
                    string propertyName = (String)entry.Key; 
                    if (_originalValues.ContainsKey(propertyName)) {
                        object propertyValue = entry.Value; 
                        // get the row values for the current column. 
                        ArrayList values = (ArrayList)_originalValues[propertyName];
                        for (int i = 0; i < values.Count; i++) { 
                            if (matches.Count <= i) { // first column
                                matches.Add(OriginalValueMatches(values[i], propertyValue));
                            }
                            else if (matches[i] == true) { // subsequent columns 
                                matches[i] = OriginalValueMatches(values[i], propertyValue);
                            } 
                        } 
                    }
                } 

                int rowIndex = matches.IndexOf(true);
                // no rows match or too many rows match.
                if ((rowIndex < 0) || (matches.IndexOf(true, rowIndex + 1) >= 0)) { 
                    throw new InvalidOperationException(AtlasWeb.LinqDataSourceView_OriginalValuesNotFound);
                } 
                // get original values for the matching row. 
                Dictionary rowValues = new Dictionary(_originalValues.Count,
                    StringComparer.OrdinalIgnoreCase); 
                foreach (DictionaryEntry entry in _originalValues) {
                    ArrayList value = (ArrayList)entry.Value;
                    rowValues.Add((string)entry.Key, value[rowIndex]);
                } 
                return rowValues;
            } 
 
            return null;
        } 

        private IDictionary GetParameterValues(IOrderedDictionary parameterValues) {
            // NOTE: Dynamic parser requires Dictionary as the last object
            // in the params array for named parameters. 
            Dictionary values = new Dictionary(parameterValues.Count,
                StringComparer.OrdinalIgnoreCase); 
            foreach (DictionaryEntry entry in parameterValues) { 
                values[(string)entry.Key] = entry.Value;
            } 
            return values;
        }

        private IDictionary GetParameterValues(ParameterCollection parameters) { 
            return GetParameterValues(parameters.GetValues(_context, _owner));
        } 
 
        protected virtual MemberInfo GetTableMemberInfo(Type contextType) {
            string tableName = TableName; 
            if (String.IsNullOrEmpty(tableName)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                    AtlasWeb.LinqDataSourceView_TableNameNotSpecified, _owner.ID));
            } 

            MemberInfo[] members = contextType.FindMembers(MemberTypes.Field | MemberTypes.Property, 
                                                           BindingFlags.Public | BindingFlags.Instance | 
                                                           BindingFlags.Static, /*filter*/null, /*filterCriteria*/null);
 
            for (int i = 0; i < members.Length; i++) {
                if (String.Equals(members[i].Name, tableName, StringComparison.OrdinalIgnoreCase)) {
                    return members[i];
                } 
            }
            return null; 
        } 

        private ReadOnlyCollection GetTableMetaDataMembers(ITable table, Type dataObjectType) { 
            DataContext context = ((ITable)table).Context;
            MetaModel contextMetaData = context.Mapping;
            MetaTable tableMetaData = contextMetaData.GetTable(dataObjectType);
            MetaType rowMetaData = tableMetaData.RowType; 
            return rowMetaData.DataMembers;
        } 
 
        public int Insert(IDictionary values) {
            return ExecuteInsert(values); 
        }

        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object",
            Justification = "Names are consistent with those used in the ObjectDataSource classes")] 
        protected virtual void InsertDataObject(object dataContext, object table, object newDataObject) {
            _linqToSql.Add((ITable)table, newDataObject); 
            _linqToSql.SubmitChanges((DataContext)dataContext); 
        }
 
        protected virtual void LoadViewState(object savedState) {
            if (savedState != null) {
                object[] myState = (object[])savedState;
 
                if (myState[0] != null) {
                    ((IStateManager)WhereParameters).LoadViewState(myState[0]); 
                } 
                if (myState[1] != null) {
                    ((IStateManager)OrderByParameters).LoadViewState(myState[1]); 
                }
                if (myState[2] != null) {
                    ((IStateManager)GroupByParameters).LoadViewState(myState[2]);
                } 
                if (myState[3] != null) {
                    ((IStateManager)OrderGroupsByParameters).LoadViewState(myState[3]); 
                } 
                if (myState[4] != null) {
                    ((IStateManager)SelectNewParameters).LoadViewState(myState[4]); 
                }
                if (myState[5] != null) {
                    _originalValues = new Hashtable((Hashtable)myState[5], StringComparer.OrdinalIgnoreCase);
                } 
            }
        } 
 
        private static bool MemberIsStatic(MemberInfo member) {
            FieldInfo field = member as FieldInfo; 
            if (field != null) {
                return field.IsStatic;
            }
            PropertyInfo property = member as PropertyInfo; 
            if (property != null) {
                MethodInfo propertyGetter = property.GetGetMethod(); 
                return ((propertyGetter != null) && propertyGetter.IsStatic); 
            }
            return false; 
        }

        private void MergeDictionaries(object dataObjectType, ParameterCollection referenceValues, IDictionary source,
                                       IDictionary destination) { 
            MergeDictionaries(dataObjectType, referenceValues, source, destination, null);
        } 
 
        private static void MergeDictionaries(object dataObjectType, ParameterCollection reference, IDictionary source,
                                              IDictionary destination, IDictionary destinationCopy) { 
            if (source != null) {
                Dictionary convertExceptions = null;
                foreach (DictionaryEntry de in source) {
                    object value = de.Value; 
                    // search for a parameter that corresponds to this dictionary entry.
                    Parameter referenceParameter = null; 
                    string parameterName = (string)de.Key; 
                    foreach (Parameter p in reference) {
                        if (String.Equals(p.Name, parameterName, StringComparison.OrdinalIgnoreCase)) { 
                            referenceParameter = p;
                            break;
                        }
                    } 
                    // use the parameter for type conversion, default value and/or converting empty string to null.
                    if (referenceParameter != null) { 
                        try { 
                            value = referenceParameter.GetValue(value, true);
                        } 
                        catch (Exception e) {
                            // catch conversion exceptions so they can be handled. Note that conversion throws various
                            // types of exceptions like InvalidCastException, FormatException, OverflowException, etc.
                            if (convertExceptions == null) { 
                                convertExceptions = new Dictionary(StringComparer.OrdinalIgnoreCase);
                            } 
                            convertExceptions[referenceParameter.Name] = e; 
                        }
                    } 
                    // save the value to the merged dictionaries.
                    destination[parameterName] = value;
                    if (destinationCopy != null) {
                        destinationCopy[parameterName] = value; 
                    }
                } 
 
                // package up conversion exceptions into single exception.
                if (convertExceptions != null) { 
                    throw new LinqDataSourceValidationException(String.Format(CultureInfo.InvariantCulture,
                        AtlasWeb.LinqDataSourceView_ValidationFailed, dataObjectType, convertExceptions.Values.First().Message), convertExceptions);
                }
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnContextCreated(LinqDataSourceStatusEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventContextCreated];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnContextCreating(LinqDataSourceContextEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventContextCreating];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnContextDisposing(LinqDataSourceDisposeEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventContextDisposing];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnDeleted(LinqDataSourceStatusEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventDeleted];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnDeleting(LinqDataSourceDeleteEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventDeleting];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnException(DynamicValidatorEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventException]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnInserted(LinqDataSourceStatusEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventInserted]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnInserting(LinqDataSourceInsertEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventInserting]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnSelected(LinqDataSourceStatusEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventSelected]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnSelecting(LinqDataSourceSelectEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventSelecting]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnUpdated(LinqDataSourceStatusEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventUpdated]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnUpdating(LinqDataSourceUpdateEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventUpdating]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        private bool OriginalValueMatches(object originalValue, object value) { 
            // NOTE: Comparing IEnumerable contents instead of instances to ensure that 
            // timestamp columns (of type byte[]) can be matched appropriately.
            IEnumerable originalValueEnumerable = originalValue as IEnumerable; 
            IEnumerable valueEnumerable = value as IEnumerable;
            if ((originalValueEnumerable != null) && (valueEnumerable != null)) {
                return LinqDataSourceHelper.EnumerableContentEquals(originalValueEnumerable, valueEnumerable);
            } 
            return originalValue.Equals(value);
        } 
 
        private void ReleaseContext(object dataContext) {
            if (dataContext != null) { 
                LinqDataSourceDisposeEventArgs disposingEventArgs = new LinqDataSourceDisposeEventArgs(dataContext);
                OnContextDisposing(disposingEventArgs);
                if (!disposingEventArgs.Cancel) {
                    IDisposable disposableObject = dataContext as IDisposable; 
                    if (disposableObject != null) {
                        disposableObject.Dispose(); 
                    } 
                }
            } 
        }

        internal void ReleaseSelectContexts() {
            if (_selectContexts != null) { 
                foreach (LinqDataSourceContextData contextData in _selectContexts) {
                    ReleaseContext(contextData.Context); 
                } 
            }
        } 

        [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters",
            Justification = "Names are consistent with those used in the ObjectDataSource classes")]
        protected virtual void ResetDataObject(object table, object dataObject) { 
            // DevDiv Bugs 187705, and 114508: Resetting is no longer necessary because
            // select has it's own context, but this method is kept for compatibility purposes. 
 
            // no-op
        } 

        private object SaveParametersViewState(ParameterCollection parameters) {
            if ((parameters != null) && (parameters.Count > 0)) {
                return ((IStateManager)parameters).SaveViewState(); 
            }
            return null; 
        } 

        protected virtual object SaveViewState() { 
            object[] myState = new object[6];
            // Saving ViewState for Selection parameters which are tracked for changes.  Parameter
            // values are updated in LoadComplete and changes will trigger a DataSourceViewChanged
            // event to indicate that data binding is required. 
            myState[0] = SaveParametersViewState(_whereParameters);
            myState[1] = SaveParametersViewState(_orderByParameters); 
            myState[2] = SaveParametersViewState(_groupByParameters); 
            myState[3] = SaveParametersViewState(_orderGroupsByParameters);
            myState[4] = SaveParametersViewState(_selectNewParameters); 
            if ((_originalValues != null) && (_originalValues.Count > 0)) {
                myState[5] = (object)_originalValues;
            }
            return myState; 
        }
 
        public IEnumerable Select(DataSourceSelectArguments arguments) { 
            return ExecuteSelect(arguments);
        } 

        private void SelectParametersChangedEventHandler(object o, EventArgs e) {
            OnDataSourceViewChanged(EventArgs.Empty);
        } 

        private Dictionary SetDataObjectProperties(object oldDataObject, object newDataObject) { 
            Dictionary validateExceptions = null; 

            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(oldDataObject); 
            foreach (PropertyDescriptor property in properties) {
                if (property.PropertyType.IsSerializable && !property.IsReadOnly) {
                    object newValue = property.GetValue(newDataObject);
                    try { 
                        property.SetValue(oldDataObject, newValue);
                    } 
                    catch (Exception e) { 
                        if (validateExceptions == null) {
                            validateExceptions = new Dictionary(StringComparer.OrdinalIgnoreCase); 
                        }
                        validateExceptions[property.Name] = e;
                    }
                } 
            }
 
            return validateExceptions; 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods",
                         Justification = "System.Data.Linq assembly will be changing to support partial trust.")]
        private void StoreOriginalValues(ITable table, Type dataObjectType, IList result) {
            // Storing columns required for Update and Delete: primary keys, timestamps and those marked for UpdateCheck. 
            // Table data is stored in a hashtable with column names for keys and an ArrayList of row data for values.
            // i.e, Hashtable { ID = ArrayList { 0, 1, 2 }, Name = ArrayList { "A", "B", "C" } } 
            ReadOnlyCollection columns = GetTableMetaDataMembers(table, dataObjectType); 
            if (columns != null) {
                int numRows = result.Count; 
                int maxColumns = columns.Count;
                List columnsToStore = new List(maxColumns);
                _originalValues = new Hashtable(maxColumns, StringComparer.OrdinalIgnoreCase);
                foreach (MetaDataMember column in columns) { 
                    if (column.Type.IsSerializable &&
                        (column.IsPrimaryKey || column.IsVersion || (column.UpdateCheck != UpdateCheck.Never))) { 
                        columnsToStore.Add(column); 
                        _originalValues[column.Member.Name] = new ArrayList(numRows);
                    } 
                }
                foreach (object currentRow in result) {
                    foreach (MetaDataMember column in columnsToStore) {
                        MetaAccessor columnAccessor = column.MemberAccessor; 
                        object value = columnAccessor.GetBoxedValue(currentRow);
                        ((ArrayList)_originalValues[column.Member.Name]).Add(value); 
                    } 
                }
            } 
        }

        private IList ToList(IQueryable query, Type dataObjectType) {
            MethodInfo toListMethod = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(dataObjectType); 
            return (IList)toListMethod.Invoke(null, new object[] { query });
        } 
 
        private void TrackParametersViewState(ParameterCollection parameters) {
            if ((parameters != null) && (parameters.Count > 0)) { 
                ((IStateManager)parameters).TrackViewState();
            }
        }
 
        protected virtual void TrackViewState() {
            _tracking = true; 
            TrackParametersViewState(_whereParameters); 
            TrackParametersViewState(_orderByParameters);
            TrackParametersViewState(_groupByParameters); 
            TrackParametersViewState(_orderGroupsByParameters);
            TrackParametersViewState(_selectNewParameters);
        }
 
        public int Update(IDictionary keys, IDictionary values, IDictionary oldValues) {
            return ExecuteUpdate(keys, values, oldValues); 
        } 

        [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", 
            Justification = "Names are consistent with those used in the ObjectDataSource classes")]
        protected virtual void UpdateDataObject(object dataContext, object table,
                                                object oldDataObject, object newDataObject) {
            _linqToSql.Attach((ITable)table, oldDataObject); 
            Dictionary validateExceptions = SetDataObjectProperties(oldDataObject, newDataObject);
 
            // package up dlinq validation exceptions into single exception. 
            if (validateExceptions != null) {
                throw new LinqDataSourceValidationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_ValidationFailed, oldDataObject.GetType(), validateExceptions.Values.First().Message), validateExceptions);
            }

            _linqToSql.SubmitChanges((DataContext)dataContext); 
        }
 
        protected virtual void ValidateContextType(Type contextType, bool selecting) { 
            if (!selecting && !typeof(DataContext).IsAssignableFrom(contextType)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_InvalidContextType, _owner.ID));
            }
        }
 
        protected virtual void ValidateDeleteSupported(IDictionary keys, IDictionary oldValues) {
            if (!CanDelete) { 
                throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture, 
                AtlasWeb.LinqDataSourceView_DeleteNotSupported, _owner.ID));
            } 
            ValidateEditSupported();
        }

        private void ValidateEditSupported() { 
            if (!String.IsNullOrEmpty(GroupBy)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_GroupByNotSupportedOnEdit, _owner.ID)); 
            }
            if (!String.IsNullOrEmpty(SelectNew)) { 
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                    AtlasWeb.LinqDataSourceView_SelectNewNotSupportedOnEdit, _owner.ID));
            }
        } 

        protected virtual void ValidateInsertSupported(IDictionary values) { 
            if (!CanInsert) { 
                throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture,
                AtlasWeb.LinqDataSourceView_InsertNotSupported, _owner.ID)); 
            }
            ValidateEditSupported();
            if ((values == null) || (values.Count == 0)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_InsertRequiresValues, _owner.ID));
            } 
        } 

        protected virtual void ValidateOrderByParameter(string name, string value) { 
            if (!_autoGenerateOrderByRegex.IsMatch(value)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                    AtlasWeb.LinqDataSourceView_InvalidOrderByFieldName, value, name));
            } 
        }
 
        protected virtual void ValidateParameterName(string name) { 
            if (!_identifierRegex.IsMatch(name)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_InvalidParameterName, name, _owner.ID));
            }
        }
 
        protected virtual void ValidateTableType(Type tableType, bool selecting) {
            if (!selecting) { 
                if (!(tableType.IsGenericType && 
                    tableType.GetGenericTypeDefinition().Equals(typeof(Table<>)))) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_InvalidTablePropertyType, _owner.ID));
                }
            }
        } 

        protected virtual void ValidateUpdateSupported(IDictionary keys, IDictionary values, IDictionary oldValues) { 
            if (!CanUpdate) { 
                throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture,
                AtlasWeb.LinqDataSourceView_UpdateNotSupported, _owner.ID)); 
            }
            ValidateEditSupported();
        }
 
        #region IStateManager implementation
        bool IStateManager.IsTrackingViewState { 
            get { 
                return IsTrackingViewState;
            } 
        }

        void IStateManager.LoadViewState(object savedState) {
            LoadViewState(savedState); 
        }
 
        object IStateManager.SaveViewState() { 
            return SaveViewState();
        } 

        void IStateManager.TrackViewState() {
            TrackViewState();
        } 
        #endregion
 
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.UI.WebControls { 
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Data.Linq; 
    using System.Data.Linq.Mapping;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization; 
    using System.Linq;
    using System.Reflection; 
    using System.Security.Permissions;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Web; 
    using System.Web.Compilation;
    using System.Web.Query.Dynamic; 
    using System.Web.Resources; 
    using DynamicValidatorEventArgs = System.Web.DynamicData.DynamicValidatorEventArgs;
    using DynamicDataSourceOperation = System.Web.DynamicData.DynamicDataSourceOperation; 

    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class LinqDataSourceView : DataSourceView, IStateManager { 

        private class LinqDataSourceAutoGeneratedWhere { 
            public LinqDataSourceAutoGeneratedWhere(string Where, IDictionary WhereParameters) { 
                this.Where = Where;
                this.WhereParameters = WhereParameters; 
            }
            public string Where { get; set; }
            public IDictionary WhereParameters;
        } 

        // This regular expression verifies that parameter names are set to valid identifiers.  This validation 
        // needs to match the parser's identifier validation as done in the default block of NextToken(). 
        private static readonly string _identifierPattern =
            @"^\s*[\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}_]" +                           // first character 
            @"[\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Nd}\p{Pc}\p{Mn}\p{Mc}\p{Cf}_]*"; // remaining characters

        private static readonly Regex _identifierRegex = new Regex(_identifierPattern + @"\s*$");
 
        private static readonly Regex _autoGenerateOrderByRegex = new Regex(_identifierPattern +
            @"(\s+(asc|ascending|desc|descending))?\s*$", RegexOptions.IgnoreCase);     // order operators 
 
        private static readonly object EventContextCreated = new object();
        private static readonly object EventContextCreating = new object(); 
        private static readonly object EventContextDisposing = new object();
        private static readonly object EventDeleted = new object();
        private static readonly object EventDeleting = new object();
        private static readonly object EventException = new object(); 
        private static readonly object EventInserted = new object();
        private static readonly object EventInserting = new object(); 
        private static readonly object EventSelected = new object(); 
        private static readonly object EventSelecting = new object();
        private static readonly object EventUpdated = new object(); 
        private static readonly object EventUpdating = new object();

        private HttpContext _context;
        private LinqDataSource _owner; 
        private bool _tracking;
 
        private bool _autoGenerateOrderByClause = false; 
        private bool _autoGenerateWhereClause = false;
        private bool _autoPage = true; 
        private bool _autoSort = true;
        private string _contextTypeName;
        private Type _contextType;
        private List _selectContexts; 
        private ParameterCollection _deleteParameters;
        private IDynamicQueryable _dynamicQueryable; 
        private bool _enableDelete = false; 
        private bool _enableInsert = false;
        private bool _enableObjectTracking = true; 
        private bool _enableUpdate = false;
        private string _groupBy;
        private ParameterCollection _groupByParameters;
        private ParameterCollection _insertParameters; 
        private ILinqToSql _linqToSql;
        private string _orderBy; 
        private ParameterCollection _orderByParameters; 
        private string _orderGroupsBy;
        private ParameterCollection _orderGroupsByParameters; 
        // using Hashtable for original values so that ObjectStateFormatter will serialize it properly in ViewState.
        private Hashtable _originalValues;
        private bool _reuseSelectContext;
        private string _selectNew; 
        private ParameterCollection _selectNewParameters;
        private bool _storeOriginalValuesInViewState = true; 
        private string _tableName; 
        private ParameterCollection _updateParameters;
        private string _where; 
        private ParameterCollection _whereParameters;

        public LinqDataSourceView(LinqDataSource owner, string name, HttpContext context)
            : this(owner, name, context, new DynamicQueryableWrapper(), new LinqToSqlWrapper()) { 
        }
 
        // internal constructor that takes mocks for unit tests. 
        internal LinqDataSourceView(LinqDataSource owner, string name, HttpContext context,
                                    IDynamicQueryable dynamicQueryable, ILinqToSql linqToSql) : base(owner, name) { 
            _owner = owner;
            _context = context;
            _dynamicQueryable = dynamicQueryable;
            _linqToSql = linqToSql; 
        }
 
        public bool AutoGenerateOrderByClause { 
            get {
                return _autoGenerateOrderByClause; 
            }
            set {
                if (_autoGenerateOrderByClause != value) {
                    _autoGenerateOrderByClause = value; 
                    OnDataSourceViewChanged(EventArgs.Empty);
                } 
            } 
        }
 
        public bool AutoGenerateWhereClause {
            get {
                return _autoGenerateWhereClause;
            } 
            set {
                if (_autoGenerateWhereClause != value) { 
                    _autoGenerateWhereClause = value; 
                    OnDataSourceViewChanged(EventArgs.Empty);
                } 
            }
        }

        public bool AutoPage { 
            get {
                return _autoPage; 
            } 
            set {
                if (_autoPage != value) { 
                    _autoPage = value;
                    OnDataSourceViewChanged(EventArgs.Empty);
                }
            } 
        }
 
        public bool AutoSort { 
            get {
                return _autoSort; 
            }
            set {
                if (_autoSort != value) {
                    _autoSort = value; 
                    OnDataSourceViewChanged(EventArgs.Empty);
                } 
            } 
        }
 
        public override bool CanDelete {
            get {
                return EnableDelete;
            } 
        }
 
        public override bool CanInsert { 
            get {
                return EnableInsert; 
            }
        }

        // When AutoPage is false the user should manually page in the Selecting event. 
        public override bool CanPage {
            get { 
                return true; 
            }
        } 

        // When AutoPage is false the user must set the total row count in the Selecting event.
        public override bool CanRetrieveTotalRowCount {
            get { 
                return true;
            } 
        } 

        // When AutoSort is false the user should manually sort in the Selecting event. 
        public override bool CanSort {
            get {
                return true;
            } 
        }
 
        public override bool CanUpdate { 
            get {
                return EnableUpdate; 
            }
        }

        protected internal virtual Type ContextType { 
            get {
                if (_contextType == null) { 
                    string typeName = ContextTypeName; 
                    if (String.IsNullOrEmpty(typeName)) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_ContextTypeNameNotSpecified, _owner.ID));
                    }
                    try {
                        _contextType = BuildManager.GetType(typeName, /*throwOnFail*/true, /*ignoreCase*/true); 
                    }
                    catch (Exception e) { 
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_ContextTypeNameNotFound, _owner.ID), e);
                    } 
                }
                return _contextType;
            }
        } 

        public virtual string ContextTypeName { 
            get { 
                return _contextTypeName ?? String.Empty;
            } 
            set {
                if (_contextTypeName != value) {
                    if (_reuseSelectContext) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_ContextTypeNameChanged, _owner.ID));
                    } 
                    _contextTypeName = value; 
                    _contextType = null;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            }
        }
 
        public ParameterCollection DeleteParameters {
            get { 
                if (_deleteParameters == null) { 
                    _deleteParameters = new ParameterCollection();
                } 
                return _deleteParameters;
            }
        }
 
        public bool EnableDelete {
            get { 
                return _enableDelete; 
            }
            set { 
                if (_enableDelete != value) {
                    _enableDelete = value;
                    OnDataSourceViewChanged(EventArgs.Empty);
                } 
            }
        } 
 
        public bool EnableInsert {
            get { 
                return _enableInsert;
            }
            set {
                if (_enableInsert != value) { 
                    _enableInsert = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                } 
            }
        } 

        public bool EnableObjectTracking {
            get {
                return _enableObjectTracking; 
            }
            set { 
                if (_enableObjectTracking != value) { 
                    if (_reuseSelectContext) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_EnableObjectTrackingChanged, _owner.ID));
                    }
                    _enableObjectTracking = value;
                } 
            }
        } 
 
        public bool EnableUpdate {
            get { 
                return _enableUpdate;
            }
            set {
                if (_enableUpdate != value) { 
                    _enableUpdate = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                } 
            }
        } 

        public string GroupBy {
            get {
                return _groupBy ?? String.Empty; 
            }
            set { 
                if (_groupBy != value) { 
                    _groupBy = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            }
        }
 
        public ParameterCollection GroupByParameters {
            get { 
                if (_groupByParameters == null) { 
                    _groupByParameters = new ParameterCollection();
                    _groupByParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler); 
                    if (_tracking) {
                        ((IStateManager)_groupByParameters).TrackViewState();
                    }
                } 
                return _groupByParameters;
            } 
        } 

        public ParameterCollection InsertParameters { 
            get {
                if (_insertParameters == null) {
                    _insertParameters = new ParameterCollection();
                } 
                return _insertParameters;
            } 
        } 

        protected bool IsTrackingViewState { 
            get {
                return _tracking;
            }
        } 

        public string OrderBy { 
            get { 
                return _orderBy ?? String.Empty;
            } 
            set {
                if (_orderBy != value) {
                    _orderBy = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            } 
        } 

        public ParameterCollection OrderByParameters { 
            get {
                if (_orderByParameters == null) {
                    _orderByParameters = new ParameterCollection();
                    _orderByParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler); 
                    if (_tracking) {
                        ((IStateManager)_orderByParameters).TrackViewState(); 
                    } 
                }
                return _orderByParameters; 
            }
        }

        public string OrderGroupsBy { 
            get {
                return _orderGroupsBy ?? String.Empty; 
            } 
            set {
                if (_orderGroupsBy != value) { 
                    _orderGroupsBy = value;
                    OnDataSourceViewChanged(EventArgs.Empty);
                }
            } 
        }
 
        public ParameterCollection OrderGroupsByParameters { 
            get {
                if (_orderGroupsByParameters == null) { 
                    _orderGroupsByParameters = new ParameterCollection();
                    _orderGroupsByParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler);
                    if (_tracking) {
                        ((IStateManager)_orderGroupsByParameters).TrackViewState(); 
                    }
                } 
                return _orderGroupsByParameters; 
            }
        } 

        [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix",
            Justification = "Removing 'New' would conflict with the Select() method.")]
        public string SelectNew { 
            get {
                return _selectNew ?? String.Empty; 
            } 
            set {
                if (_selectNew != value) { 
                    _selectNew = value;
                    OnDataSourceViewChanged(EventArgs.Empty);
                }
            } 
        }
 
        public ParameterCollection SelectNewParameters { 
            get {
                if (_selectNewParameters == null) { 
                    _selectNewParameters = new ParameterCollection();
                    _selectNewParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler);
                    if (_tracking) {
                        ((IStateManager)_selectNewParameters).TrackViewState(); 
                    }
                } 
                return _selectNewParameters; 
            }
        } 

        public bool StoreOriginalValuesInViewState {
            get {
                return _storeOriginalValuesInViewState; 
            }
            set { 
                if (_storeOriginalValuesInViewState != value) { 
                    _storeOriginalValuesInViewState = value;
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            }
        }
 
        public string TableName {
            get { 
                return _tableName ?? String.Empty; 
            }
            set { 
                if (_tableName != value) {
                    if (_reuseSelectContext) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                            AtlasWeb.LinqDataSourceView_TableNameChanged, _owner.ID)); 
                    }
                    _tableName = value; 
                    OnDataSourceViewChanged(EventArgs.Empty); 
                }
            } 
        }

        public ParameterCollection UpdateParameters {
            get { 
                if (_updateParameters == null) {
                    _updateParameters = new ParameterCollection(); 
                } 
                return _updateParameters;
            } 
        }

        public string Where {
            get { 
                return _where ?? String.Empty;
            } 
            set { 
                if (_where != value) {
                    _where = value; 
                    OnDataSourceViewChanged(EventArgs.Empty);
                }
            }
        } 

        public ParameterCollection WhereParameters { 
            get { 
                if (_whereParameters == null) {
                    _whereParameters = new ParameterCollection(); 
                    _whereParameters.ParametersChanged += new EventHandler(SelectParametersChangedEventHandler);
                    if (_tracking) {
                        ((IStateManager)_whereParameters).TrackViewState();
                    } 
                }
                return _whereParameters; 
            } 
        }
 
        public event EventHandler ContextCreated {
            add {
                Events.AddHandler(EventContextCreated, value);
            } 
            remove {
                Events.RemoveHandler(EventContextCreated, value); 
            } 
        }
 
        public event EventHandler ContextCreating {
            add {
                Events.AddHandler(EventContextCreating, value);
            } 
            remove {
                Events.RemoveHandler(EventContextCreating, value); 
            } 
        }
 
        public event EventHandler ContextDisposing {
            add {
                Events.AddHandler(EventContextDisposing, value);
            } 
            remove {
                Events.RemoveHandler(EventContextDisposing, value); 
            } 
        }
 
        public event EventHandler Deleted {
            add {
                Events.AddHandler(EventDeleted, value);
            } 
            remove {
                Events.RemoveHandler(EventDeleted, value); 
            } 
        }
 
        public event EventHandler Deleting {
            add {
                Events.AddHandler(EventDeleting, value);
            } 
            remove {
                Events.RemoveHandler(EventDeleting, value); 
            } 
        }
 
        internal event EventHandler Exception {
            add {
                Events.AddHandler(EventException, value);
            } 
            remove {
                Events.RemoveHandler(EventException, value); 
            } 
        }
 
        public event EventHandler Inserted {
            add {
                Events.AddHandler(EventInserted, value);
            } 
            remove {
                Events.RemoveHandler(EventInserted, value); 
            } 
        }
 
        public event EventHandler Inserting {
            add {
                Events.AddHandler(EventInserting, value);
            } 
            remove {
                Events.RemoveHandler(EventInserting, value); 
            } 
        }
 
        public event EventHandler Selected {
            add {
                Events.AddHandler(EventSelected, value);
            } 
            remove {
                Events.RemoveHandler(EventSelected, value); 
            } 
        }
 
        public event EventHandler Selecting {
            add {
                Events.AddHandler(EventSelecting, value);
            } 
            remove {
                Events.RemoveHandler(EventSelecting, value); 
            } 
        }
 
        public event EventHandler Updated {
            add {
                Events.AddHandler(EventUpdated, value);
            } 
            remove {
                Events.RemoveHandler(EventUpdated, value); 
            } 
        }
 
        public event EventHandler Updating {
            add {
                Events.AddHandler(EventUpdating, value);
            } 
            remove {
                Events.RemoveHandler(EventUpdating, value); 
            } 
        }
 
        private static IQueryable AsQueryable(object o) {
            IQueryable oQueryable = o as IQueryable;
            if (oQueryable != null) {
                return oQueryable; 
            }
 
            // Wrap strings in IEnumerable instead of treating as IEnumerable. 
            string oString = o as string;
            if (oString != null) { 
                return Queryable.AsQueryable(new string[] { oString });
            }

            IEnumerable oEnumerable = o as IEnumerable; 
            if (oEnumerable != null) {
                // IEnumerable can be directly converted to an IQueryable. 
                Type genericType = LinqDataSourceHelper.FindGenericEnumerableType(o.GetType()); 
                if (genericType != null) {
                    // The non-generic Queryable.AsQueryable gets called for array types, executing 
                    // the FindGenericType logic again.  Might want to investigate way to avoid this.
                    return Queryable.AsQueryable(oEnumerable);
                }
                // Wrap non-generic IEnumerables in IEnumerable. 
                List genericList = new List();
                foreach (object item in oEnumerable) { 
                    genericList.Add(item); 
                }
                return Queryable.AsQueryable(genericList); 
            }

            // Wrap non-IEnumerable types in IEnumerable.
            Type listType = typeof(List<>).MakeGenericType(o.GetType()); 
            IList list = (IList)CreateObjectInstance(listType);
            list.Add(o); 
            return Queryable.AsQueryable(list); 
        }
 
        private object BuildDataObject(Type dataObjectType, IDictionary inputParameters) {
            object dataObject = CreateObjectInstance(dataObjectType);

            Dictionary convertOrValidateExceptions = null; 
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(dataObject);
            foreach (DictionaryEntry de in inputParameters) { 
                string propName = (de.Key == null ? String.Empty : de.Key.ToString()); 
                PropertyDescriptor property = props.Find(propName, /*ignoreCase*/true);
                // NOTE: No longer throws when a property is not found or is read only.  This makes 
                // Delete, Insert and Update operations more optimistic, allowing scenarios such as:
                // 1) Deletes and Updates after projecting data in the Selecting event.
                // 2) Deletes and Updates after selecting children of the data object type in the
                //    Selecting event. 
                if ((property != null) && (!property.IsReadOnly)) {
                    try { 
                        object value = BuildObjectValue(de.Value, property.PropertyType, propName); 
                        property.SetValue(dataObject, value);
                    } 
                    catch (Exception e) {
                        if (convertOrValidateExceptions == null) {
                            convertOrValidateExceptions = new Dictionary(
                                StringComparer.OrdinalIgnoreCase); 
                        }
                        convertOrValidateExceptions[property.Name] = e; 
                    } 
                }
            } 

            // package up conversion or dlinq validation exceptions into single exception.
            if (convertOrValidateExceptions != null) {
                // Include the text of the first exception as part of the full exception, 
                // to make it less cryptic in scenarios where it gets shown.
                throw new LinqDataSourceValidationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_ValidationFailed, dataObjectType, convertOrValidateExceptions.Values.First().Message), 
                    convertOrValidateExceptions);
            } 

            return dataObject;
        }
 
        private LinqDataSourceEditData BuildDeleteDataObject(object table, IDictionary keys, IDictionary oldValues) {
            Type dataObjectType = GetDataObjectType(table.GetType()); 
            IDictionary caseInsensitiveOldValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); 
            IDictionary originalValues = GetOriginalValues(keys);
 
            ParameterCollection deleteParameters = DeleteParameters;
            MergeDictionaries(dataObjectType, deleteParameters, keys, caseInsensitiveOldValues);
            MergeDictionaries(dataObjectType, deleteParameters, oldValues, caseInsensitiveOldValues);
            if (originalValues != null) { 
                MergeDictionaries(dataObjectType, deleteParameters, originalValues, caseInsensitiveOldValues);
            } 
 
            LinqDataSourceEditData editData = new LinqDataSourceEditData();
            editData.OriginalDataObject = BuildDataObject(dataObjectType, caseInsensitiveOldValues); 
            return editData;
        }

        private LinqDataSourceEditData BuildInsertDataObject(object table, IDictionary values) { 
            Type dataObjectType = GetDataObjectType(table.GetType());
            IDictionary caseInsensitiveNewValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); 
            MergeDictionaries(dataObjectType, InsertParameters, InsertParameters.GetValues(_context, _owner), 
                caseInsensitiveNewValues);
            MergeDictionaries(dataObjectType, InsertParameters, values, caseInsensitiveNewValues); 

            LinqDataSourceEditData editData = new LinqDataSourceEditData();
            editData.NewDataObject = BuildDataObject(dataObjectType, caseInsensitiveNewValues);
            return editData; 
        }
 
        internal static object BuildObjectValue(object value, Type destinationType, string paramName) { 
            // NOTE: This method came from ObjectDataSource with no changes made.
            // Only consider converting the type if the value is non-null and the types don't match 
            if ((value != null) && (!destinationType.IsInstanceOfType(value))) {
                Type innerDestinationType = destinationType;
                bool isNullable = false;
                if (destinationType.IsGenericType && 
                    (destinationType.GetGenericTypeDefinition() == typeof(Nullable<>))) {
                    innerDestinationType = destinationType.GetGenericArguments()[0]; 
                    isNullable = true; 
                }
                else { 
                    if (destinationType.IsByRef) {
                        innerDestinationType = destinationType.GetElementType();
                    }
                } 

                // Try to convert from for example string to DateTime, so that 
                // afterwards we can convert DateTime to Nullable 

                // If the value is a string, we attempt to use a TypeConverter to convert it 
                value = ConvertType(value, innerDestinationType, paramName);

                // Special-case the value when the destination is Nullable
                if (isNullable) { 
                    Type paramValueType = value.GetType();
                    if (innerDestinationType != paramValueType) { 
                        // Throw if for example, we are trying to convert from int to Nullable 
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                            AtlasWeb.LinqDataSourceView_CannotConvertType, paramName, paramValueType.FullName, 
                            String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>",
                            destinationType.GetGenericArguments()[0].FullName)));
                    }
                } 
            }
            return value; 
        } 

        private LinqDataSourceEditData BuildUpdateDataObjects(object table, IDictionary keys, 
                                                              IDictionary values, IDictionary oldValues) {
            Type dataObjectType = GetDataObjectType(table.GetType());
            IDictionary caseInsensitiveNewValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase);
            IDictionary caseInsensitiveOldValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); 
            IDictionary originalValues = GetOriginalValues(keys);
 
            // We start out with the old values, just to pre-populate the list with items 
            // that might not have corresponding new values. For example if a GridView has
            // a read-only field, there will be an old value, but no new value. The data object 
            // still has to have *some* value for a given field, so we just use the old value.
            ParameterCollection updateParameters = UpdateParameters;
            MergeDictionaries(dataObjectType, updateParameters, oldValues, caseInsensitiveOldValues, caseInsensitiveNewValues);
            MergeDictionaries(dataObjectType, updateParameters, keys, caseInsensitiveOldValues, caseInsensitiveNewValues); 
            if (originalValues != null) {
                MergeDictionaries(dataObjectType, updateParameters, originalValues, caseInsensitiveOldValues, caseInsensitiveNewValues); 
            } 
            MergeDictionaries(dataObjectType, updateParameters, values, caseInsensitiveNewValues);
 
            LinqDataSourceEditData editData = new LinqDataSourceEditData();
            editData.NewDataObject = BuildDataObject(dataObjectType, caseInsensitiveNewValues);
            editData.OriginalDataObject = BuildDataObject(dataObjectType, caseInsensitiveOldValues);
            return editData; 
        }
 
        private static object ConvertType(object value, Type type, string paramName) { 
            // NOTE: This method came from ObjectDataSource with no changes made.
            string s = value as string; 
            if (s != null) {
                // Get the type converter for the destination type
                TypeConverter converter = TypeDescriptor.GetConverter(type);
                if (converter != null) { 
                    // Perform the conversion
                    try { 
                        value = converter.ConvertFromString(s); 
                    }
                    catch (NotSupportedException) { 
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                            AtlasWeb.LinqDataSourceView_CannotConvertType, paramName, typeof(string).FullName,
                            type.FullName));
                    } 
                    catch (FormatException) {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                            AtlasWeb.LinqDataSourceView_CannotConvertType, paramName, typeof(string).FullName, 
                            type.FullName));
                    } 
                }
            }
            return value;
        } 

        protected virtual object CreateContext(Type contextType) { 
            return CreateObjectInstance(contextType); 
        }
 
        private LinqDataSourceContextData CreateContextAndTable(DataSourceOperation operation) {
            LinqDataSourceContextData contextData = null;
            bool eventFired = false;
            try { 
                LinqDataSourceContextEventArgs contextEventArgs = new LinqDataSourceContextEventArgs(operation);
                OnContextCreating(contextEventArgs); 
 
                contextData = new LinqDataSourceContextData(contextEventArgs.ObjectInstance);
                Type contextType = null; 
                MemberInfo tableMemberInfo = null;
                if (contextData.Context == null) {
                    // construct the context unless accessing a static table for Select.
                    contextType = ContextType; 
                    tableMemberInfo = GetTableMemberInfo(contextType);
                    if (tableMemberInfo != null) { 
                        if (MemberIsStatic(tableMemberInfo)) { 
                            if (operation != DataSourceOperation.Select) {
                                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                                    AtlasWeb.LinqDataSourceView_TableCannotBeStatic, TableName, contextType.Name, _owner.ID));
                            }
                        }
                        else { 
                            contextData.Context = CreateContext(contextType);
                            contextData.IsNewContext = true; 
                        } 
                    }
                } 
                else {
                    // use the manually constructed context.
                    tableMemberInfo = GetTableMemberInfo(contextData.Context.GetType());
                } 

                // fetch the table from the context. 
                if (tableMemberInfo != null) { 
                    FieldInfo field = tableMemberInfo as FieldInfo;
                    if (field != null) { 
                        contextData.Table = field.GetValue(contextData.Context);
                    }
                    PropertyInfo property = tableMemberInfo as PropertyInfo;
                    if (property != null) { 
                        contextData.Table = property.GetValue(contextData.Context, null);
                    } 
                } 
                if (contextData.Table == null) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_TableNameNotFound, TableName, contextType.Name, _owner.ID));
                }
            }
            catch (Exception e) { 
                eventFired = true;
                LinqDataSourceStatusEventArgs createdEventArgs = new LinqDataSourceStatusEventArgs(e); 
                OnContextCreated(createdEventArgs); 
                OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.ContextCreate));
                // CreateContextAndTable will return null if this exception is handled. 
                if (!createdEventArgs.ExceptionHandled) {
                    throw;
                }
            } 
            finally {
                if (!eventFired) { 
                    // contextData can be null if exception thrown from ContextCreating handler. 
                    object context = (contextData == null) ? null : contextData.Context;
                    LinqDataSourceStatusEventArgs createdEventArgs = new LinqDataSourceStatusEventArgs(context); 
                    OnContextCreated(createdEventArgs);
                }
            }
            return contextData; 
        }
 
        private LinqDataSourceContextData CreateContextAndTableForEdit(DataSourceOperation operation) { 
            LinqDataSourceContextData contextData = CreateContextAndTable(operation);
            // context data may be null or incomplete if an exception was handled 
            if (contextData != null) {
                if (contextData.Context == null) {
                    return null;
                } 
                if (contextData.Table == null) {
                    ReleaseContext(contextData.Context); 
                    return null; 
                }
                ValidateContextType(contextData.Context.GetType(), false); 
                ValidateTableType(contextData.Table.GetType(), false);
            }
            return contextData;
        } 

        private LinqDataSourceContextData CreateContextAndTableForSelect() { 
            if (_selectContexts == null) { 
                _selectContexts = new List();
            } 
            else if (_reuseSelectContext && _selectContexts.Count > 0) {
                return _selectContexts[_selectContexts.Count - 1];
            }
 
            // context data may be null if an exception was handled
            LinqDataSourceContextData contextData = CreateContextAndTable(DataSourceOperation.Select); 
            if (contextData != null) { 
                if (contextData.Context != null) {
                     ValidateContextType(contextData.Context.GetType(), true); 
                }
                if (contextData.Table != null) {
                     ValidateTableType(contextData.Table.GetType(), true);
                } 

                _selectContexts.Add(contextData); 
 
                // context may not be dlinq context or may be null if table was static.
                DataContext dlinqContext = contextData.Context as DataContext; 
                if ((dlinqContext != null) && contextData.IsNewContext) {
                    dlinqContext.ObjectTrackingEnabled = EnableObjectTracking;
                }
                // don't reuse dlinq contexts that cache data or exterior changes will not be reflected. 
                _reuseSelectContext = (dlinqContext == null) || !EnableObjectTracking;
            } 
            return contextData; 
        }
 
        private static object CreateObjectInstance(Type type) {
            // FastCreatePublicInstance is faster than Activator.CreateInstance since it caches the type factories.
            return HttpRuntime.FastCreatePublicInstance(type);
        } 

        public int Delete(IDictionary keys, IDictionary oldValues) { 
            return ExecuteDelete(keys, oldValues); 
        }
 
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object",
            Justification = "Names are consistent with those used in the ObjectDataSource classes")]
        protected virtual void DeleteDataObject(object dataContext, object table, object oldDataObject) {
            _linqToSql.Attach((ITable)table, oldDataObject); 
            _linqToSql.Remove((ITable)table, oldDataObject);
            _linqToSql.SubmitChanges((DataContext)dataContext); 
        } 

        private IDictionary EscapeParameterKeys(IDictionary parameters) { 
            Dictionary escapedParameters = new Dictionary(parameters.Count,
                StringComparer.OrdinalIgnoreCase);
            foreach (KeyValuePair parameter in parameters) {
                string key = parameter.Key; 
                if (String.IsNullOrEmpty(key)) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_ParametersMustBeNamed, _owner.ID)); 
                }
                ValidateParameterName(key); 
                escapedParameters.Add('@' + key, parameter.Value);
            }
            return escapedParameters;
        } 

        protected override int ExecuteDelete(IDictionary keys, IDictionary oldValues) { 
            ValidateDeleteSupported(keys, oldValues); 
            LinqDataSourceContextData contextData = null;
            try { 
                contextData = CreateContextAndTableForEdit(DataSourceOperation.Delete);
                if (contextData != null) {
                    LinqDataSourceEditData editData = null;
                    LinqDataSourceDeleteEventArgs deleteEventArgs = null; 
                    try {
                        editData = BuildDeleteDataObject(contextData.Table, keys, oldValues); 
                    } 
                    catch (LinqDataSourceValidationException e) {
                        // allow user to handle conversion or dlinq property validation exceptions. 
                        deleteEventArgs = new LinqDataSourceDeleteEventArgs(e);
                        OnDeleting(deleteEventArgs);
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Delete));
                        if (deleteEventArgs.ExceptionHandled) { 
                            return -1;
                        } 
                        throw; 
                    }
                    deleteEventArgs = new LinqDataSourceDeleteEventArgs(editData.OriginalDataObject); 
                    OnDeleting(deleteEventArgs);
                    if (deleteEventArgs.Cancel) {
                        return -1;
                    } 

                    LinqDataSourceStatusEventArgs deletedEventArgs = null; 
                    try { 
                        DeleteDataObject(contextData.Context, contextData.Table, deleteEventArgs.OriginalObject);
                    } 
                    catch (Exception e) {
                        // allow user to handle dlinq exceptions including OnValidate validation.
                        deletedEventArgs = new LinqDataSourceStatusEventArgs(e);
                        OnDeleted(deletedEventArgs); 
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Delete));
                        if (deletedEventArgs.ExceptionHandled) { 
                            return -1; 
                        }
                        throw; 
                    }
                    deletedEventArgs = new LinqDataSourceStatusEventArgs(deleteEventArgs.OriginalObject);
                    OnDeleted(deletedEventArgs);
                } 
            }
            finally { 
                if (contextData != null) { 
                    ReleaseContext(contextData.Context);
                } 
            }
            // estimated number of rows deleted.
            return 1;
        } 

        protected override int ExecuteInsert(IDictionary values) { 
            ValidateInsertSupported(values); 
            LinqDataSourceContextData contextData = null;
            try { 
                contextData = CreateContextAndTableForEdit(DataSourceOperation.Insert);
                if (contextData != null) {
                    LinqDataSourceEditData editData = null;
                    LinqDataSourceInsertEventArgs insertEventArgs = null; 
                    try {
                        editData = BuildInsertDataObject(contextData.Table, values); 
                    } 
                    catch (LinqDataSourceValidationException e) {
                        // allow user to handle conversion or dlinq property validation exceptions. 
                        insertEventArgs = new LinqDataSourceInsertEventArgs(e);
                        OnInserting(insertEventArgs);
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Insert));
                        if (insertEventArgs.ExceptionHandled) { 
                            return -1;
                        } 
                        throw; 
                    }
                    insertEventArgs = new LinqDataSourceInsertEventArgs(editData.NewDataObject); 
                    OnInserting(insertEventArgs);
                    if (insertEventArgs.Cancel) {
                        return -1;
                    } 

                    LinqDataSourceStatusEventArgs insertedEventArgs = null; 
                    try { 
                        InsertDataObject(contextData.Context, contextData.Table, insertEventArgs.NewObject);
                    } 
                    catch (Exception e) {
                        // allow user to handle dlinq exceptions including OnValidate validation.
                        insertedEventArgs = new LinqDataSourceStatusEventArgs(e);
                        OnInserted(insertedEventArgs); 
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Insert));
                        if (insertedEventArgs.ExceptionHandled) { 
                            return -1; 
                        }
                        throw; 
                    }
                    insertedEventArgs = new LinqDataSourceStatusEventArgs(insertEventArgs.NewObject);
                    OnInserted(insertedEventArgs);
                } 
            }
            finally { 
                if (contextData != null) { 
                    ReleaseContext(contextData.Context);
                } 
            }
            // estimated number of rows inserted.
            return 1;
        } 

        protected internal override IEnumerable ExecuteSelect(DataSourceSelectArguments arguments) { 
            if (arguments == null) { 
                throw new ArgumentNullException("arguments");
            } 

            _originalValues = null;
            IDictionary whereParameters = GetParameterValues(WhereParameters);
            IOrderedDictionary orderByParameters = GetOrderedParameterValues(OrderByParameters); 
            IDictionary groupByParameters = GetParameterValues(GroupByParameters);
            IDictionary orderGroupsByParameters = GetParameterValues(OrderGroupsByParameters); 
            IDictionary selectNewParameters = GetParameterValues(SelectNewParameters); 

            LinqDataSourceSelectEventArgs selectEventArgs = new LinqDataSourceSelectEventArgs(arguments, 
                whereParameters, orderByParameters, groupByParameters, orderGroupsByParameters, selectNewParameters);
            OnSelecting(selectEventArgs);
            if (selectEventArgs.Cancel) {
                return null; 
            }
 
            object selectResult = selectEventArgs.Result; 
            object table = selectResult;
 
            // Original values should only be stored for valid delete and update scenarios.
            bool storeOriginalValues = StoreOriginalValuesInViewState && (CanDelete || CanUpdate) &&
                String.IsNullOrEmpty(GroupBy) && String.IsNullOrEmpty(SelectNew);
 
            if (selectResult == null) {
                LinqDataSourceContextData contextData = CreateContextAndTableForSelect(); 
                if (contextData != null) { 
                    selectResult = contextData.Table;
                    table = contextData.Table; 
                }
            }
            // If the provided select result was not a DLinq table and we need to store
            // original values then we must get the table and create a new data context 
            // instance so that we can access the column metadata.
            else if (!(table is ITable) && storeOriginalValues) { 
                LinqDataSourceContextData contextData = CreateContextAndTableForSelect(); 
                if (contextData != null) {
                    table = contextData.Table; 
                }
            }

            return ExecuteSelectQuery(selectEventArgs, selectResult, table, storeOriginalValues); 
        }
 
        private IQueryable ExecuteSelectAutoSortAndPage(IQueryable source, DataSourceSelectArguments arguments) { 
            IQueryable result = source;
            string sortExpression = arguments.SortExpression; 
            if (AutoSort && (!String.IsNullOrEmpty(sortExpression))) {
                result = _dynamicQueryable.OrderBy(result, sortExpression);
            }
            if (AutoPage) { 
                if (arguments.RetrieveTotalRowCount) {
                    arguments.TotalRowCount = _dynamicQueryable.Count(result); 
                } 
                if ((arguments.MaximumRows > 0) && (arguments.StartRowIndex >= 0)) {
                    result = _dynamicQueryable.Skip(result, arguments.StartRowIndex); 
                    result = _dynamicQueryable.Take(result, arguments.MaximumRows);
                }
            }
            else if (arguments.RetrieveTotalRowCount && (arguments.TotalRowCount == -1)) { 
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                    AtlasWeb.LinqDataSourceView_PagingNotHandled, _owner.ID)); 
            } 
            return result;
        } 

        private IQueryable ExecuteSelectExpressions(IQueryable source, IDictionary whereValues,
                                                    IOrderedDictionary orderByOrderedValues,
                                                    IDictionary groupByValues, 
                                                    IDictionary orderGroupsByValues,
                                                    IDictionary selectNewValues) { 
            IQueryable result = source; 
            string where = Where;
            if (AutoGenerateWhereClause) { 
                if (!String.IsNullOrEmpty(where)) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                        AtlasWeb.LinqDataSourceView_WhereAlreadySpecified, _owner.ID));
                } 
                LinqDataSourceAutoGeneratedWhere generatedWhere = GenerateWhereClauseAndEscapeParameterKeys(whereValues);
                if (!String.IsNullOrEmpty(generatedWhere.Where)) { 
                    result = _dynamicQueryable.Where(result, generatedWhere.Where, generatedWhere.WhereParameters); 
                }
            } 
            else if (!String.IsNullOrEmpty(where)) {
                result = _dynamicQueryable.Where(result, where, EscapeParameterKeys(whereValues));
            }
 
            string orderBy = OrderBy;
            IDictionary orderByValues = null; 
            if (AutoGenerateOrderByClause) { 
                if (!String.IsNullOrEmpty(orderBy)) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_OrderByAlreadySpecified, _owner.ID));
                }
                orderBy = GenerateOrderByClause(orderByOrderedValues);
                orderByValues = new Dictionary(0); 
            }
            else { 
                orderByValues = GetParameterValues(orderByOrderedValues); 
            }
            if (!String.IsNullOrEmpty(orderBy)) { 
                result = _dynamicQueryable.OrderBy(result, orderBy, EscapeParameterKeys(orderByValues));
            }

            string groupBy = GroupBy; 
            if (String.IsNullOrEmpty(groupBy)) {
                if (!String.IsNullOrEmpty(OrderGroupsBy)) { 
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_OrderGroupsByRequiresGroupBy, _owner.ID));
                } 
            }
            else {
                result = _dynamicQueryable.GroupBy(result, groupBy, "it", EscapeParameterKeys(groupByValues));
                string orderGroupsBy = OrderGroupsBy; 
                if (!String.IsNullOrEmpty(orderGroupsBy)) {
                    result = _dynamicQueryable.OrderBy(result, orderGroupsBy, EscapeParameterKeys(orderGroupsByValues)); 
                } 
            }
 
            string selectNew = SelectNew;
            if (!String.IsNullOrEmpty(selectNew)) {
                result = _dynamicQueryable.Select(result, selectNew, EscapeParameterKeys(selectNewValues));
            } 

            return result; 
        } 

        private IEnumerable ExecuteSelectQuery(LinqDataSourceSelectEventArgs selectEventArgs, object selectResult, 
                                               object table, bool storeOriginalValues) {
            IList result = null;
            if (selectResult != null) {
                try { 
                    IQueryable query = AsQueryable(selectResult);
                    query = ExecuteSelectExpressions(query, selectEventArgs.WhereParameters, 
                                                     selectEventArgs.OrderByParameters, 
                                                     selectEventArgs.GroupByParameters,
                                                     selectEventArgs.OrderGroupsByParameters, 
                                                     selectEventArgs.SelectParameters);
                    query = ExecuteSelectAutoSortAndPage(query, selectEventArgs.Arguments);

                    Type dataObjectType = GetDataObjectType(query.GetType()); 
                    result = ToList(query, dataObjectType);
 
                    if (storeOriginalValues) { 
                        ITable dlinqTable = table as ITable;
                        if ((dlinqTable != null) && dataObjectType.Equals(GetDataObjectType(dlinqTable.GetType()))) { 
                            StoreOriginalValues(dlinqTable, dataObjectType, result);
                        }
                    }
                } 
                catch (Exception e) {
                    result = null; 
                    LinqDataSourceStatusEventArgs selectedEventArgs = new LinqDataSourceStatusEventArgs(e); 
                    OnSelected(selectedEventArgs);
                    OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Select)); 
                    if (!selectedEventArgs.ExceptionHandled) {
                        throw;
                    }
                } 
                finally {
                    if (result != null) { 
                        int totalRowCount = -1; // paging performed, but row count not available. 
                        if (selectEventArgs.Arguments.RetrieveTotalRowCount) {
                            totalRowCount = selectEventArgs.Arguments.TotalRowCount; 
                        }
                        else if (!AutoPage) {
                            totalRowCount = result.Count;
                        } 
                        LinqDataSourceStatusEventArgs selectedEventArgs = new LinqDataSourceStatusEventArgs(result, totalRowCount);
                        OnSelected(selectedEventArgs); 
                    } 
                }
            } 
            return result;
        }

        protected override int ExecuteUpdate(IDictionary keys, IDictionary values, IDictionary oldValues) { 
            ValidateUpdateSupported(keys, values, oldValues);
            LinqDataSourceContextData contextData = null; 
            try { 
                contextData = CreateContextAndTableForEdit(DataSourceOperation.Update);
                if (contextData != null) { 
                    LinqDataSourceEditData editData = null;
                    LinqDataSourceUpdateEventArgs updateEventArgs = null;
                    try {
                        editData = BuildUpdateDataObjects(contextData.Table, keys, values, oldValues); 
                    }
                    catch (LinqDataSourceValidationException e) { 
                        // allow user to handle conversion or dlinq property validation exceptions. 
                        updateEventArgs = new LinqDataSourceUpdateEventArgs(e);
                        OnUpdating(updateEventArgs); 
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Update));
                        if (updateEventArgs.ExceptionHandled) {
                            return -1;
                        } 
                        throw;
                    } 
                    updateEventArgs = new LinqDataSourceUpdateEventArgs(editData.OriginalDataObject, editData.NewDataObject); 
                    OnUpdating(updateEventArgs);
                    if (updateEventArgs.Cancel) { 
                        return -1;
                    }

                    LinqDataSourceStatusEventArgs updatedEventArgs = null; 
                    try {
                        UpdateDataObject(contextData.Context, contextData.Table, updateEventArgs.OriginalObject, updateEventArgs.NewObject); 
                    } 
                    catch (Exception e) {
                        ResetDataObject(contextData.Table, updateEventArgs.OriginalObject); 
                        // allow user to handle dlinq exceptions including OnValidate validation.
                        updatedEventArgs = new LinqDataSourceStatusEventArgs(e);
                        OnUpdated(updatedEventArgs);
                        OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Update)); 
                        if (updatedEventArgs.ExceptionHandled) {
                            return -1; 
                        } 
                        throw;
                    } 
                    updatedEventArgs = new LinqDataSourceStatusEventArgs(updateEventArgs.NewObject);
                    OnUpdated(updatedEventArgs);
                }
            } 
            finally {
                if (contextData != null) { 
                    ReleaseContext(contextData.Context); 
                }
            } 
            // estimated number of rows updated.
            return 1;
        }
 
        private string GenerateOrderByClause(IOrderedDictionary orderByParameters) {
            if ((orderByParameters != null) && (orderByParameters.Count > 0)) { 
                StringBuilder orderBy = new StringBuilder(); 
                foreach (DictionaryEntry parameter in orderByParameters) {
                    string value = (string)parameter.Value; 
                    // exclude null and empty values.
                    if (!String.IsNullOrEmpty(value)) {
                        string name = (string)parameter.Key;
                        ValidateOrderByParameter(name, value); 
                        if (orderBy.Length > 0) {
                            orderBy.Append(", "); 
                        } 
                        orderBy.Append(value);
                    } 
                }
                return orderBy.ToString();
            }
            return String.Empty; 
        }
 
        private LinqDataSourceAutoGeneratedWhere GenerateWhereClauseAndEscapeParameterKeys(IDictionary whereParameters) { 
            if ((whereParameters != null) && (whereParameters.Count > 0)) {
                Dictionary escapedParameters = new Dictionary(whereParameters.Count); 
                StringBuilder where = new StringBuilder();
                int index = 0;
                foreach (KeyValuePair parameter in whereParameters) {
                    string key = parameter.Key; 
                    string value = (parameter.Value == null) ? null : parameter.Value.ToString();
                    // exclude null and empty values. 
                    if (!(String.IsNullOrEmpty(key) || String.IsNullOrEmpty(value))) { 
                        string newKey = "@p" + index++;
                        if (where.Length > 0) { 
                            where.Append(" AND ");
                        }
                        where.Append(key);
                        where.Append(" == "); 
                        where.Append(newKey);
                        escapedParameters.Add(newKey, parameter.Value); 
                    } 
                }
                return new LinqDataSourceAutoGeneratedWhere(where.ToString(), escapedParameters); 
            }
            return new LinqDataSourceAutoGeneratedWhere(String.Empty, null);
        }
 
        protected virtual Type GetDataObjectType(Type tableType) {
            if (tableType.IsGenericType) { 
                Type[] genericTypes = tableType.GetGenericArguments(); 
                if (genericTypes.Length == 1) {
                    return genericTypes[0]; 
                }
            }
            return typeof(object);
        } 

        private IOrderedDictionary GetOrderedParameterValues(ParameterCollection parameters) { 
            IOrderedDictionary orderedValues = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); 
            IDictionary parameterValues = parameters.GetValues(_context, _owner);
            foreach (DictionaryEntry entry in parameterValues) { 
                orderedValues[entry.Key] = entry.Value;
            }
            return orderedValues;
        } 

        private IDictionary GetOriginalValues(IDictionary keys) { 
            // Table data is stored in a hashtable with column names for keys and an ArrayList of row data for values. 
            // i.e, Hashtable { ID = ArrayList { 0, 1, 2 }, Name = ArrayList { "A", "B", "C" } }
            if (_originalValues != null) { 
                // matches list keeps track of row indexes which match.
                List matches = new List();
                foreach (DictionaryEntry entry in keys) {
                    string propertyName = (String)entry.Key; 
                    if (_originalValues.ContainsKey(propertyName)) {
                        object propertyValue = entry.Value; 
                        // get the row values for the current column. 
                        ArrayList values = (ArrayList)_originalValues[propertyName];
                        for (int i = 0; i < values.Count; i++) { 
                            if (matches.Count <= i) { // first column
                                matches.Add(OriginalValueMatches(values[i], propertyValue));
                            }
                            else if (matches[i] == true) { // subsequent columns 
                                matches[i] = OriginalValueMatches(values[i], propertyValue);
                            } 
                        } 
                    }
                } 

                int rowIndex = matches.IndexOf(true);
                // no rows match or too many rows match.
                if ((rowIndex < 0) || (matches.IndexOf(true, rowIndex + 1) >= 0)) { 
                    throw new InvalidOperationException(AtlasWeb.LinqDataSourceView_OriginalValuesNotFound);
                } 
                // get original values for the matching row. 
                Dictionary rowValues = new Dictionary(_originalValues.Count,
                    StringComparer.OrdinalIgnoreCase); 
                foreach (DictionaryEntry entry in _originalValues) {
                    ArrayList value = (ArrayList)entry.Value;
                    rowValues.Add((string)entry.Key, value[rowIndex]);
                } 
                return rowValues;
            } 
 
            return null;
        } 

        private IDictionary GetParameterValues(IOrderedDictionary parameterValues) {
            // NOTE: Dynamic parser requires Dictionary as the last object
            // in the params array for named parameters. 
            Dictionary values = new Dictionary(parameterValues.Count,
                StringComparer.OrdinalIgnoreCase); 
            foreach (DictionaryEntry entry in parameterValues) { 
                values[(string)entry.Key] = entry.Value;
            } 
            return values;
        }

        private IDictionary GetParameterValues(ParameterCollection parameters) { 
            return GetParameterValues(parameters.GetValues(_context, _owner));
        } 
 
        protected virtual MemberInfo GetTableMemberInfo(Type contextType) {
            string tableName = TableName; 
            if (String.IsNullOrEmpty(tableName)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                    AtlasWeb.LinqDataSourceView_TableNameNotSpecified, _owner.ID));
            } 

            MemberInfo[] members = contextType.FindMembers(MemberTypes.Field | MemberTypes.Property, 
                                                           BindingFlags.Public | BindingFlags.Instance | 
                                                           BindingFlags.Static, /*filter*/null, /*filterCriteria*/null);
 
            for (int i = 0; i < members.Length; i++) {
                if (String.Equals(members[i].Name, tableName, StringComparison.OrdinalIgnoreCase)) {
                    return members[i];
                } 
            }
            return null; 
        } 

        private ReadOnlyCollection GetTableMetaDataMembers(ITable table, Type dataObjectType) { 
            DataContext context = ((ITable)table).Context;
            MetaModel contextMetaData = context.Mapping;
            MetaTable tableMetaData = contextMetaData.GetTable(dataObjectType);
            MetaType rowMetaData = tableMetaData.RowType; 
            return rowMetaData.DataMembers;
        } 
 
        public int Insert(IDictionary values) {
            return ExecuteInsert(values); 
        }

        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object",
            Justification = "Names are consistent with those used in the ObjectDataSource classes")] 
        protected virtual void InsertDataObject(object dataContext, object table, object newDataObject) {
            _linqToSql.Add((ITable)table, newDataObject); 
            _linqToSql.SubmitChanges((DataContext)dataContext); 
        }
 
        protected virtual void LoadViewState(object savedState) {
            if (savedState != null) {
                object[] myState = (object[])savedState;
 
                if (myState[0] != null) {
                    ((IStateManager)WhereParameters).LoadViewState(myState[0]); 
                } 
                if (myState[1] != null) {
                    ((IStateManager)OrderByParameters).LoadViewState(myState[1]); 
                }
                if (myState[2] != null) {
                    ((IStateManager)GroupByParameters).LoadViewState(myState[2]);
                } 
                if (myState[3] != null) {
                    ((IStateManager)OrderGroupsByParameters).LoadViewState(myState[3]); 
                } 
                if (myState[4] != null) {
                    ((IStateManager)SelectNewParameters).LoadViewState(myState[4]); 
                }
                if (myState[5] != null) {
                    _originalValues = new Hashtable((Hashtable)myState[5], StringComparer.OrdinalIgnoreCase);
                } 
            }
        } 
 
        private static bool MemberIsStatic(MemberInfo member) {
            FieldInfo field = member as FieldInfo; 
            if (field != null) {
                return field.IsStatic;
            }
            PropertyInfo property = member as PropertyInfo; 
            if (property != null) {
                MethodInfo propertyGetter = property.GetGetMethod(); 
                return ((propertyGetter != null) && propertyGetter.IsStatic); 
            }
            return false; 
        }

        private void MergeDictionaries(object dataObjectType, ParameterCollection referenceValues, IDictionary source,
                                       IDictionary destination) { 
            MergeDictionaries(dataObjectType, referenceValues, source, destination, null);
        } 
 
        private static void MergeDictionaries(object dataObjectType, ParameterCollection reference, IDictionary source,
                                              IDictionary destination, IDictionary destinationCopy) { 
            if (source != null) {
                Dictionary convertExceptions = null;
                foreach (DictionaryEntry de in source) {
                    object value = de.Value; 
                    // search for a parameter that corresponds to this dictionary entry.
                    Parameter referenceParameter = null; 
                    string parameterName = (string)de.Key; 
                    foreach (Parameter p in reference) {
                        if (String.Equals(p.Name, parameterName, StringComparison.OrdinalIgnoreCase)) { 
                            referenceParameter = p;
                            break;
                        }
                    } 
                    // use the parameter for type conversion, default value and/or converting empty string to null.
                    if (referenceParameter != null) { 
                        try { 
                            value = referenceParameter.GetValue(value, true);
                        } 
                        catch (Exception e) {
                            // catch conversion exceptions so they can be handled. Note that conversion throws various
                            // types of exceptions like InvalidCastException, FormatException, OverflowException, etc.
                            if (convertExceptions == null) { 
                                convertExceptions = new Dictionary(StringComparer.OrdinalIgnoreCase);
                            } 
                            convertExceptions[referenceParameter.Name] = e; 
                        }
                    } 
                    // save the value to the merged dictionaries.
                    destination[parameterName] = value;
                    if (destinationCopy != null) {
                        destinationCopy[parameterName] = value; 
                    }
                } 
 
                // package up conversion exceptions into single exception.
                if (convertExceptions != null) { 
                    throw new LinqDataSourceValidationException(String.Format(CultureInfo.InvariantCulture,
                        AtlasWeb.LinqDataSourceView_ValidationFailed, dataObjectType, convertExceptions.Values.First().Message), convertExceptions);
                }
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnContextCreated(LinqDataSourceStatusEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventContextCreated];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnContextCreating(LinqDataSourceContextEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventContextCreating];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnContextDisposing(LinqDataSourceDisposeEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventContextDisposing];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnDeleted(LinqDataSourceStatusEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventDeleted];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnDeleting(LinqDataSourceDeleteEventArgs e) {
            EventHandler handler = 
                (EventHandler)Events[EventDeleting];
            if (handler != null) {
                handler(this, e);
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnException(DynamicValidatorEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventException]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnInserted(LinqDataSourceStatusEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventInserted]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnInserting(LinqDataSourceInsertEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventInserting]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnSelected(LinqDataSourceStatusEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventSelected]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnSelecting(LinqDataSourceSelectEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventSelecting]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnUpdated(LinqDataSourceStatusEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventUpdated]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnUpdating(LinqDataSourceUpdateEventArgs e) { 
            EventHandler handler =
                (EventHandler)Events[EventUpdating]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        private bool OriginalValueMatches(object originalValue, object value) { 
            // NOTE: Comparing IEnumerable contents instead of instances to ensure that 
            // timestamp columns (of type byte[]) can be matched appropriately.
            IEnumerable originalValueEnumerable = originalValue as IEnumerable; 
            IEnumerable valueEnumerable = value as IEnumerable;
            if ((originalValueEnumerable != null) && (valueEnumerable != null)) {
                return LinqDataSourceHelper.EnumerableContentEquals(originalValueEnumerable, valueEnumerable);
            } 
            return originalValue.Equals(value);
        } 
 
        private void ReleaseContext(object dataContext) {
            if (dataContext != null) { 
                LinqDataSourceDisposeEventArgs disposingEventArgs = new LinqDataSourceDisposeEventArgs(dataContext);
                OnContextDisposing(disposingEventArgs);
                if (!disposingEventArgs.Cancel) {
                    IDisposable disposableObject = dataContext as IDisposable; 
                    if (disposableObject != null) {
                        disposableObject.Dispose(); 
                    } 
                }
            } 
        }

        internal void ReleaseSelectContexts() {
            if (_selectContexts != null) { 
                foreach (LinqDataSourceContextData contextData in _selectContexts) {
                    ReleaseContext(contextData.Context); 
                } 
            }
        } 

        [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters",
            Justification = "Names are consistent with those used in the ObjectDataSource classes")]
        protected virtual void ResetDataObject(object table, object dataObject) { 
            // DevDiv Bugs 187705, and 114508: Resetting is no longer necessary because
            // select has it's own context, but this method is kept for compatibility purposes. 
 
            // no-op
        } 

        private object SaveParametersViewState(ParameterCollection parameters) {
            if ((parameters != null) && (parameters.Count > 0)) {
                return ((IStateManager)parameters).SaveViewState(); 
            }
            return null; 
        } 

        protected virtual object SaveViewState() { 
            object[] myState = new object[6];
            // Saving ViewState for Selection parameters which are tracked for changes.  Parameter
            // values are updated in LoadComplete and changes will trigger a DataSourceViewChanged
            // event to indicate that data binding is required. 
            myState[0] = SaveParametersViewState(_whereParameters);
            myState[1] = SaveParametersViewState(_orderByParameters); 
            myState[2] = SaveParametersViewState(_groupByParameters); 
            myState[3] = SaveParametersViewState(_orderGroupsByParameters);
            myState[4] = SaveParametersViewState(_selectNewParameters); 
            if ((_originalValues != null) && (_originalValues.Count > 0)) {
                myState[5] = (object)_originalValues;
            }
            return myState; 
        }
 
        public IEnumerable Select(DataSourceSelectArguments arguments) { 
            return ExecuteSelect(arguments);
        } 

        private void SelectParametersChangedEventHandler(object o, EventArgs e) {
            OnDataSourceViewChanged(EventArgs.Empty);
        } 

        private Dictionary SetDataObjectProperties(object oldDataObject, object newDataObject) { 
            Dictionary validateExceptions = null; 

            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(oldDataObject); 
            foreach (PropertyDescriptor property in properties) {
                if (property.PropertyType.IsSerializable && !property.IsReadOnly) {
                    object newValue = property.GetValue(newDataObject);
                    try { 
                        property.SetValue(oldDataObject, newValue);
                    } 
                    catch (Exception e) { 
                        if (validateExceptions == null) {
                            validateExceptions = new Dictionary(StringComparer.OrdinalIgnoreCase); 
                        }
                        validateExceptions[property.Name] = e;
                    }
                } 
            }
 
            return validateExceptions; 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods",
                         Justification = "System.Data.Linq assembly will be changing to support partial trust.")]
        private void StoreOriginalValues(ITable table, Type dataObjectType, IList result) {
            // Storing columns required for Update and Delete: primary keys, timestamps and those marked for UpdateCheck. 
            // Table data is stored in a hashtable with column names for keys and an ArrayList of row data for values.
            // i.e, Hashtable { ID = ArrayList { 0, 1, 2 }, Name = ArrayList { "A", "B", "C" } } 
            ReadOnlyCollection columns = GetTableMetaDataMembers(table, dataObjectType); 
            if (columns != null) {
                int numRows = result.Count; 
                int maxColumns = columns.Count;
                List columnsToStore = new List(maxColumns);
                _originalValues = new Hashtable(maxColumns, StringComparer.OrdinalIgnoreCase);
                foreach (MetaDataMember column in columns) { 
                    if (column.Type.IsSerializable &&
                        (column.IsPrimaryKey || column.IsVersion || (column.UpdateCheck != UpdateCheck.Never))) { 
                        columnsToStore.Add(column); 
                        _originalValues[column.Member.Name] = new ArrayList(numRows);
                    } 
                }
                foreach (object currentRow in result) {
                    foreach (MetaDataMember column in columnsToStore) {
                        MetaAccessor columnAccessor = column.MemberAccessor; 
                        object value = columnAccessor.GetBoxedValue(currentRow);
                        ((ArrayList)_originalValues[column.Member.Name]).Add(value); 
                    } 
                }
            } 
        }

        private IList ToList(IQueryable query, Type dataObjectType) {
            MethodInfo toListMethod = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(dataObjectType); 
            return (IList)toListMethod.Invoke(null, new object[] { query });
        } 
 
        private void TrackParametersViewState(ParameterCollection parameters) {
            if ((parameters != null) && (parameters.Count > 0)) { 
                ((IStateManager)parameters).TrackViewState();
            }
        }
 
        protected virtual void TrackViewState() {
            _tracking = true; 
            TrackParametersViewState(_whereParameters); 
            TrackParametersViewState(_orderByParameters);
            TrackParametersViewState(_groupByParameters); 
            TrackParametersViewState(_orderGroupsByParameters);
            TrackParametersViewState(_selectNewParameters);
        }
 
        public int Update(IDictionary keys, IDictionary values, IDictionary oldValues) {
            return ExecuteUpdate(keys, values, oldValues); 
        } 

        [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", 
            Justification = "Names are consistent with those used in the ObjectDataSource classes")]
        protected virtual void UpdateDataObject(object dataContext, object table,
                                                object oldDataObject, object newDataObject) {
            _linqToSql.Attach((ITable)table, oldDataObject); 
            Dictionary validateExceptions = SetDataObjectProperties(oldDataObject, newDataObject);
 
            // package up dlinq validation exceptions into single exception. 
            if (validateExceptions != null) {
                throw new LinqDataSourceValidationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_ValidationFailed, oldDataObject.GetType(), validateExceptions.Values.First().Message), validateExceptions);
            }

            _linqToSql.SubmitChanges((DataContext)dataContext); 
        }
 
        protected virtual void ValidateContextType(Type contextType, bool selecting) { 
            if (!selecting && !typeof(DataContext).IsAssignableFrom(contextType)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_InvalidContextType, _owner.ID));
            }
        }
 
        protected virtual void ValidateDeleteSupported(IDictionary keys, IDictionary oldValues) {
            if (!CanDelete) { 
                throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture, 
                AtlasWeb.LinqDataSourceView_DeleteNotSupported, _owner.ID));
            } 
            ValidateEditSupported();
        }

        private void ValidateEditSupported() { 
            if (!String.IsNullOrEmpty(GroupBy)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_GroupByNotSupportedOnEdit, _owner.ID)); 
            }
            if (!String.IsNullOrEmpty(SelectNew)) { 
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                    AtlasWeb.LinqDataSourceView_SelectNewNotSupportedOnEdit, _owner.ID));
            }
        } 

        protected virtual void ValidateInsertSupported(IDictionary values) { 
            if (!CanInsert) { 
                throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture,
                AtlasWeb.LinqDataSourceView_InsertNotSupported, _owner.ID)); 
            }
            ValidateEditSupported();
            if ((values == null) || (values.Count == 0)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_InsertRequiresValues, _owner.ID));
            } 
        } 

        protected virtual void ValidateOrderByParameter(string name, string value) { 
            if (!_autoGenerateOrderByRegex.IsMatch(value)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
                    AtlasWeb.LinqDataSourceView_InvalidOrderByFieldName, value, name));
            } 
        }
 
        protected virtual void ValidateParameterName(string name) { 
            if (!_identifierRegex.IsMatch(name)) {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                    AtlasWeb.LinqDataSourceView_InvalidParameterName, name, _owner.ID));
            }
        }
 
        protected virtual void ValidateTableType(Type tableType, bool selecting) {
            if (!selecting) { 
                if (!(tableType.IsGenericType && 
                    tableType.GetGenericTypeDefinition().Equals(typeof(Table<>)))) {
                    throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, 
                        AtlasWeb.LinqDataSourceView_InvalidTablePropertyType, _owner.ID));
                }
            }
        } 

        protected virtual void ValidateUpdateSupported(IDictionary keys, IDictionary values, IDictionary oldValues) { 
            if (!CanUpdate) { 
                throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture,
                AtlasWeb.LinqDataSourceView_UpdateNotSupported, _owner.ID)); 
            }
            ValidateEditSupported();
        }
 
        #region IStateManager implementation
        bool IStateManager.IsTrackingViewState { 
            get { 
                return IsTrackingViewState;
            } 
        }

        void IStateManager.LoadViewState(object savedState) {
            LoadViewState(savedState); 
        }
 
        object IStateManager.SaveViewState() { 
            return SaveViewState();
        } 

        void IStateManager.TrackViewState() {
            TrackViewState();
        } 
        #endregion
 
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK