LinqDataView.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 / DataSet / System / Data / LinqDataView.cs / 1 / LinqDataView.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
//----------------------------------------------------------------------------- 
using System; 
using System.Collections;
using System.Collections.Generic; 
using System.Linq;
using System.Diagnostics;
using System.ComponentModel;
using System.Data; 
using System.Text;
using System.Data.DataSetExtensions; 
 
namespace System.Data
{ 
    /// 
    /// Represents a bindable, queryable DataView of DataRow, that can be created from from LINQ queries over DataTable
    /// and from DataTable.
    ///  
    internal class LinqDataView : DataView, IBindingList, IBindingListView
    { 
        ///  
        /// A Comparer that compares a Key and a Row.
        ///  
        internal Func comparerKeyRow;  // comparer for DataView.Find(..

        /// 
        /// Builds the sort expression in case multiple selector/comparers are added 
        /// 
        internal readonly SortExpressionBuilder sortExpressionBuilder; 
 
        /// 
        /// Constructs a LinkDataView and its parent DataView. 
        /// Does not create index on the DataView since filter and sort expressions are not yet provided.
        /// 
        /// The input table from which LinkDataView is to be created.
        internal LinqDataView(DataTable table, SortExpressionBuilder sortExpressionBuilder) 
            : base(table)
        { 
            Debug.Assert(table != null, "null DataTable"); 
            this.sortExpressionBuilder = sortExpressionBuilder ?? new SortExpressionBuilder();
        } 


        //I have two forms of predicate because I need to pass in null if predicate is null. Otherwise I need to convert it into delegate and pass it into
        // data view's constructor. That logic for checking null can't be embedded in the base constructor call. 
        /// 
        /// 
        ///  
        /// Table from which to create the view
        /// User-provided filter-predicate as a Func, bool>"/> 
        /// User-provided predicate but in the form of System.Predicate
        /// Predicates are being replicated in different forms so that nulls can be passed in.
        /// For e.g. when user provides null predicate, base.Predicate should be set to null. I cant do that in the constructor initialization
        /// if I will have to create System.Predicate delegate from Func. 
        /// 
        /// The comparer function of DataRow to be used for sorting.  
        /// A comparer function that compares a Key value to DataRow. 
        /// Whether sorting is ascending or descending.
        /// Row state filter. For the purpose of LinkDataView it should always be CurrentRows. 
        internal LinqDataView(
                    DataTable table,
                    Func predicate_func,
                    Predicate predicate_system, 
                    Comparison comparison,
                    Func comparerKeyRow, 
                    SortExpressionBuilder sortExpressionBuilder) 

                //Parent constructor 
            : base(table,
                predicate_system,
                comparison,
                DataViewRowState.CurrentRows) 
        {
            this.sortExpressionBuilder = (sortExpressionBuilder == null) ? this.sortExpressionBuilder : sortExpressionBuilder; 
            this.comparerKeyRow = comparerKeyRow; 
        }
 
        /// 
        /// Gets or sets the expression used to filter which rows are viewed in the LinqDataView
        /// 
        public override string RowFilter 
        {
            get 
            { 
                if (base.RowPredicate == null)//using string based filter or no filter
                { 
                    return base.RowFilter;
                }
                else //using expression based filter
                { 
                    return null;
                } 
            } 

            set 
            {
                if (value == null)
                {
                    base.RowPredicate = null; 
                    base.RowFilter = String.Empty; //INDEX rebuild twice
                } 
                else 
                {
                    base.RowFilter = value; 
                    base.RowPredicate = null;
                }
            }
        } 

        #region Find 
 
        /// 
        /// Searches the index and finds a single row where the sort-key matches the input key 
        /// 
        /// Value of the key to find
        /// Index of the first match of input key
        internal override int FindByKey(object key) 
        {
            /////////////// Preconditions //////////////// 
            //check that both string and expression based sort are never simultaneously set 
            Debug.Assert(base.Sort != null);
            Debug.Assert(!(!String.IsNullOrEmpty(base.Sort) && base.SortComparison != null)); 
            /////////////////////////////////////////////

            if (!String.IsNullOrEmpty(base.Sort))  //use find for DV's sort string
            { 
                return base.FindByKey(key);
            } 
            else if (base.SortComparison == null) //neither string or expr set 
            {
                //This is the exception message from DataView that we want to use 
                throw ExceptionBuilder.IndexKeyLength(0, 0);
            }
            else  //find for expression based sort
            { 
                if (sortExpressionBuilder.Count !=1)
                    throw DataSetUtil.InvalidOperation(Strings.LDV_InvalidNumOfKeys(sortExpressionBuilder.Count)); 
 
                Index.ComparisonBySelector compareDelg =
                    new Index.ComparisonBySelector(comparerKeyRow); 

                List keyList = new List();
                keyList.Add(key);
                Range range = FindRecords(compareDelg, keyList); 

                return (range.Count == 0) ? -1 : range.Min; 
            } 
        }
 
        /// 
        /// Since LinkDataView does not support multiple selectors/comparers, it does not make sense for
        /// them to Find using multiple keys.
        /// This overriden method prevents users calling multi-key find on dataview. 
        /// 
        internal override int FindByKey(object[] key) 
        { 
            //---------Checks ----------------
            //must have string or expression based sort specified 
            if (base.SortComparison == null && String.IsNullOrEmpty(base.Sort))
            {
                //This is the exception message from DataView that we want to use
                throw ExceptionBuilder.IndexKeyLength(0, 0); 
            }
            else if (base.SortComparison != null && key.Length != sortExpressionBuilder.Count) 
            { 
                throw DataSetUtil.InvalidOperation(Strings.LDV_InvalidNumOfKeys(sortExpressionBuilder.Count));
            } 
            //--------------------------------

            if (base.SortComparison == null)//using string to sort
                return base.FindByKey(key); 
            else
            { 
                Index.ComparisonBySelector compareDelg = 
                    new Index.ComparisonBySelector(comparerKeyRow);
 
                List keyList = new List();
                foreach (object singleKey in key)
                {
                    keyList.Add(singleKey); 
                }
                Range range = FindRecords(compareDelg, keyList); 
                return (range.Count == 0) ? -1 : range.Min; 
            }
 
        }

        /// 
        /// Searches the index and finds rows where the sort-key matches the input key. 
        /// Since LinkDataView does not support multiple selectors/comparers, it does not make sense for
        /// them to Find using multiple keys. This overriden method prevents users calling multi-key find on dataview. 
        ///  
        internal override DataRowView[] FindRowsByKey(object[] key)
        { 
            //---------Checks ----------------
            //must have string or expression based sort specified
            if (base.SortComparison == null && String.IsNullOrEmpty(base.Sort))
            { 
                //This is the exception message from DataView that we want to use
                throw ExceptionBuilder.IndexKeyLength(0, 0); 
            } 
            else if (base.SortComparison != null && key.Length != sortExpressionBuilder.Count)
            { 
                throw DataSetUtil.InvalidOperation(Strings.LDV_InvalidNumOfKeys(sortExpressionBuilder.Count));
            }
            //--------------------------------
 
            if (base.SortComparison == null)//using string to sort
            { 
                return base.FindRowsByKey(key); 
            }
            else 
            {
                Range range = FindRecords(
                    new Index.ComparisonBySelector(comparerKeyRow),
                    new List(key)); 
                return base.GetDataRowViewFromRange(range);
            } 
        } 
        #endregion
 

        #region Misc Overrides
        /// 
        /// Overriding DataView's SetIndex to prevent users from setting RowState filter to anything other 
        /// than CurrentRows.
        ///  
        internal override void SetIndex(string newSort, DataViewRowState newRowStates, IFilter newRowFilter) 
        {
            //Throw only if expressions (filter or sort) are used and rowstate is not current rows 
            if ( (base.SortComparison != null || base.RowPredicate != null)
                    && newRowStates != DataViewRowState.CurrentRows)
            {
                throw DataSetUtil.Argument(Strings.LDVRowStateError); 
            }
            else 
            { 
                base.SetIndex(newSort, newRowStates, newRowFilter);
            } 
        }

        #endregion
 
        #region IBindingList
 
        ///  
        /// Clears both expression-based and DataView's string-based sorting.
        ///  
        void IBindingList.RemoveSort()
        {
            base.Sort = String.Empty;
            base.SortComparison = null; 
        }
 
        ///  
        /// Overrides IBindingList's SortProperty so that it returns null if expression based sort
        /// is used in the LinkDataView, otherwise it defers the result to DataView 
        /// 
        PropertyDescriptor IBindingList.SortProperty
        {
            get 
            {
                return (base.SortComparison == null) ? base.GetSortProperty() : null; 
            } 
        }
 
        /// 
        /// Overrides IBindingList's SortDescriptions so that it returns null if expression based sort
        /// is used in the LinkDataView, otherwise it defers the result to DataView
        ///  
        ListSortDescriptionCollection IBindingListView.SortDescriptions
        { 
            get 
            {
                if (base.SortComparison == null) 
                {
                    return base.GetSortDescriptions();
                }
                else 
                {
                    return new ListSortDescriptionCollection(); 
                } 
            }
        } 

        /// 
        /// Tells whether the LinqDataView is sorted or not
        ///  
        bool IBindingList.IsSorted
        { 
            get 
            {   //Sorted if either expression based sort or string based sort is set
                return !(base.SortComparison == null && base.Sort.Length == 0); 
            }
        }

        #endregion 
    }
} 
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
//----------------------------------------------------------------------------- 
using System; 
using System.Collections;
using System.Collections.Generic; 
using System.Linq;
using System.Diagnostics;
using System.ComponentModel;
using System.Data; 
using System.Text;
using System.Data.DataSetExtensions; 
 
namespace System.Data
{ 
    /// 
    /// Represents a bindable, queryable DataView of DataRow, that can be created from from LINQ queries over DataTable
    /// and from DataTable.
    ///  
    internal class LinqDataView : DataView, IBindingList, IBindingListView
    { 
        ///  
        /// A Comparer that compares a Key and a Row.
        ///  
        internal Func comparerKeyRow;  // comparer for DataView.Find(..

        /// 
        /// Builds the sort expression in case multiple selector/comparers are added 
        /// 
        internal readonly SortExpressionBuilder sortExpressionBuilder; 
 
        /// 
        /// Constructs a LinkDataView and its parent DataView. 
        /// Does not create index on the DataView since filter and sort expressions are not yet provided.
        /// 
        /// The input table from which LinkDataView is to be created.
        internal LinqDataView(DataTable table, SortExpressionBuilder sortExpressionBuilder) 
            : base(table)
        { 
            Debug.Assert(table != null, "null DataTable"); 
            this.sortExpressionBuilder = sortExpressionBuilder ?? new SortExpressionBuilder();
        } 


        //I have two forms of predicate because I need to pass in null if predicate is null. Otherwise I need to convert it into delegate and pass it into
        // data view's constructor. That logic for checking null can't be embedded in the base constructor call. 
        /// 
        /// 
        ///  
        /// Table from which to create the view
        /// User-provided filter-predicate as a Func, bool>"/> 
        /// User-provided predicate but in the form of System.Predicate
        /// Predicates are being replicated in different forms so that nulls can be passed in.
        /// For e.g. when user provides null predicate, base.Predicate should be set to null. I cant do that in the constructor initialization
        /// if I will have to create System.Predicate delegate from Func. 
        /// 
        /// The comparer function of DataRow to be used for sorting.  
        /// A comparer function that compares a Key value to DataRow. 
        /// Whether sorting is ascending or descending.
        /// Row state filter. For the purpose of LinkDataView it should always be CurrentRows. 
        internal LinqDataView(
                    DataTable table,
                    Func predicate_func,
                    Predicate predicate_system, 
                    Comparison comparison,
                    Func comparerKeyRow, 
                    SortExpressionBuilder sortExpressionBuilder) 

                //Parent constructor 
            : base(table,
                predicate_system,
                comparison,
                DataViewRowState.CurrentRows) 
        {
            this.sortExpressionBuilder = (sortExpressionBuilder == null) ? this.sortExpressionBuilder : sortExpressionBuilder; 
            this.comparerKeyRow = comparerKeyRow; 
        }
 
        /// 
        /// Gets or sets the expression used to filter which rows are viewed in the LinqDataView
        /// 
        public override string RowFilter 
        {
            get 
            { 
                if (base.RowPredicate == null)//using string based filter or no filter
                { 
                    return base.RowFilter;
                }
                else //using expression based filter
                { 
                    return null;
                } 
            } 

            set 
            {
                if (value == null)
                {
                    base.RowPredicate = null; 
                    base.RowFilter = String.Empty; //INDEX rebuild twice
                } 
                else 
                {
                    base.RowFilter = value; 
                    base.RowPredicate = null;
                }
            }
        } 

        #region Find 
 
        /// 
        /// Searches the index and finds a single row where the sort-key matches the input key 
        /// 
        /// Value of the key to find
        /// Index of the first match of input key
        internal override int FindByKey(object key) 
        {
            /////////////// Preconditions //////////////// 
            //check that both string and expression based sort are never simultaneously set 
            Debug.Assert(base.Sort != null);
            Debug.Assert(!(!String.IsNullOrEmpty(base.Sort) && base.SortComparison != null)); 
            /////////////////////////////////////////////

            if (!String.IsNullOrEmpty(base.Sort))  //use find for DV's sort string
            { 
                return base.FindByKey(key);
            } 
            else if (base.SortComparison == null) //neither string or expr set 
            {
                //This is the exception message from DataView that we want to use 
                throw ExceptionBuilder.IndexKeyLength(0, 0);
            }
            else  //find for expression based sort
            { 
                if (sortExpressionBuilder.Count !=1)
                    throw DataSetUtil.InvalidOperation(Strings.LDV_InvalidNumOfKeys(sortExpressionBuilder.Count)); 
 
                Index.ComparisonBySelector compareDelg =
                    new Index.ComparisonBySelector(comparerKeyRow); 

                List keyList = new List();
                keyList.Add(key);
                Range range = FindRecords(compareDelg, keyList); 

                return (range.Count == 0) ? -1 : range.Min; 
            } 
        }
 
        /// 
        /// Since LinkDataView does not support multiple selectors/comparers, it does not make sense for
        /// them to Find using multiple keys.
        /// This overriden method prevents users calling multi-key find on dataview. 
        /// 
        internal override int FindByKey(object[] key) 
        { 
            //---------Checks ----------------
            //must have string or expression based sort specified 
            if (base.SortComparison == null && String.IsNullOrEmpty(base.Sort))
            {
                //This is the exception message from DataView that we want to use
                throw ExceptionBuilder.IndexKeyLength(0, 0); 
            }
            else if (base.SortComparison != null && key.Length != sortExpressionBuilder.Count) 
            { 
                throw DataSetUtil.InvalidOperation(Strings.LDV_InvalidNumOfKeys(sortExpressionBuilder.Count));
            } 
            //--------------------------------

            if (base.SortComparison == null)//using string to sort
                return base.FindByKey(key); 
            else
            { 
                Index.ComparisonBySelector compareDelg = 
                    new Index.ComparisonBySelector(comparerKeyRow);
 
                List keyList = new List();
                foreach (object singleKey in key)
                {
                    keyList.Add(singleKey); 
                }
                Range range = FindRecords(compareDelg, keyList); 
                return (range.Count == 0) ? -1 : range.Min; 
            }
 
        }

        /// 
        /// Searches the index and finds rows where the sort-key matches the input key. 
        /// Since LinkDataView does not support multiple selectors/comparers, it does not make sense for
        /// them to Find using multiple keys. This overriden method prevents users calling multi-key find on dataview. 
        ///  
        internal override DataRowView[] FindRowsByKey(object[] key)
        { 
            //---------Checks ----------------
            //must have string or expression based sort specified
            if (base.SortComparison == null && String.IsNullOrEmpty(base.Sort))
            { 
                //This is the exception message from DataView that we want to use
                throw ExceptionBuilder.IndexKeyLength(0, 0); 
            } 
            else if (base.SortComparison != null && key.Length != sortExpressionBuilder.Count)
            { 
                throw DataSetUtil.InvalidOperation(Strings.LDV_InvalidNumOfKeys(sortExpressionBuilder.Count));
            }
            //--------------------------------
 
            if (base.SortComparison == null)//using string to sort
            { 
                return base.FindRowsByKey(key); 
            }
            else 
            {
                Range range = FindRecords(
                    new Index.ComparisonBySelector(comparerKeyRow),
                    new List(key)); 
                return base.GetDataRowViewFromRange(range);
            } 
        } 
        #endregion
 

        #region Misc Overrides
        /// 
        /// Overriding DataView's SetIndex to prevent users from setting RowState filter to anything other 
        /// than CurrentRows.
        ///  
        internal override void SetIndex(string newSort, DataViewRowState newRowStates, IFilter newRowFilter) 
        {
            //Throw only if expressions (filter or sort) are used and rowstate is not current rows 
            if ( (base.SortComparison != null || base.RowPredicate != null)
                    && newRowStates != DataViewRowState.CurrentRows)
            {
                throw DataSetUtil.Argument(Strings.LDVRowStateError); 
            }
            else 
            { 
                base.SetIndex(newSort, newRowStates, newRowFilter);
            } 
        }

        #endregion
 
        #region IBindingList
 
        ///  
        /// Clears both expression-based and DataView's string-based sorting.
        ///  
        void IBindingList.RemoveSort()
        {
            base.Sort = String.Empty;
            base.SortComparison = null; 
        }
 
        ///  
        /// Overrides IBindingList's SortProperty so that it returns null if expression based sort
        /// is used in the LinkDataView, otherwise it defers the result to DataView 
        /// 
        PropertyDescriptor IBindingList.SortProperty
        {
            get 
            {
                return (base.SortComparison == null) ? base.GetSortProperty() : null; 
            } 
        }
 
        /// 
        /// Overrides IBindingList's SortDescriptions so that it returns null if expression based sort
        /// is used in the LinkDataView, otherwise it defers the result to DataView
        ///  
        ListSortDescriptionCollection IBindingListView.SortDescriptions
        { 
            get 
            {
                if (base.SortComparison == null) 
                {
                    return base.GetSortDescriptions();
                }
                else 
                {
                    return new ListSortDescriptionCollection(); 
                } 
            }
        } 

        /// 
        /// Tells whether the LinqDataView is sorted or not
        ///  
        bool IBindingList.IsSorted
        { 
            get 
            {   //Sorted if either expression based sort or string based sort is set
                return !(base.SortComparison == null && base.Sort.Length == 0); 
            }
        }

        #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