DataSource.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / DataSource.cs / 1 / DataSource.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.InfoCards
{ 
    using System;
    using System.Collections.Generic; 
    using System.Globalization; 
    using System.Threading;
    using Microsoft.InfoCards.Diagnostics; 
    using System.ServiceModel.Diagnostics;

    using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace;
 
    //
    // Summary: 
    //  Abstract base class for all data sources in the inforcard system. 
    //
    // Remarks: 
    //  Currently, only FileDataSource exists, but during the original design,
    //  we had the requirement for an AD data source, so we have left this
    //  abstracted implementation alone, for future expansion.
    // 
    internal abstract class DataSource : IDisposable
    { 
        string              m_instanceId; 
        bool                m_isLoaded;
        ReaderWriterLock    m_lock; 
        bool                m_isDisposed;
        string              m_sourceId;
        bool                m_isCleared;
 

 
        protected DataSource( string instanceId, string sourceId ) 
        {
            m_instanceId = instanceId; 
            m_sourceId = sourceId;
            m_lock = new ReaderWriterLock( );
        }
 
        public string SourceId
        { 
            get 
            {
                ThrowIfDisposed( ); 
                return m_sourceId;
            }
        }
        public bool IsDisposed 
        {
            get 
            { 
                return m_isDisposed;
            } 
        }

        public bool IsLoaded
        { 
            get
            { 
                ThrowIfDisposed( ); 
                return m_isLoaded;
            } 
        }

        public bool IsCleared
        { 
            get
            { 
                return m_isCleared; 
            }
            set 
            {
                m_isCleared = value;
            }
        } 

        protected internal string InstanceId 
        { 
            get
            { 
                ThrowIfDisposed( );
                return m_instanceId;
            }
            set 
            {
                ThrowIfDisposed( ); 
                m_instanceId = value; 
            }
        } 

        public bool IsProcessingTransaction()
        {
 
            ThrowIfDisposed();
            ThrowIfNotLoaded(); 
            return m_lock.IsWriterLockHeld; 
        }
 
        public void BeginTransaction()
        {
            ThrowIfWriteLockHeld();
            ThrowIfDisposed( ); 
            ThrowIfNotLoaded( );
 
            IDT.TraceVerbose( 
                    TraceCode.StoreBeginTransaction,
                    SourceId ); 

            m_lock.AcquireWriterLock( 0 );

            OnBeginTransaction( ); 
        }
        public void CommitTransaction() 
        { 
            ThrowIfDisposed( );
            ThrowIfNotLoaded( ); 
            ThrowIfWriteLockNotHeld( );

            IDT.TraceVerbose(
                    TraceCode.StoreCommitTransaction, 
                    SourceId );
 
            OnCommitTransaction( ); 
            m_lock.ReleaseWriterLock( );
        } 
        public void RollbackTransaction()
        {
            ThrowIfDisposed( );
            ThrowIfNotLoaded( ); 
            ThrowIfWriteLockNotHeld( );
            IDT.TraceVerbose( 
                    TraceCode.StoreRollbackTransaction, 
                    SourceId );
 
            OnRollbackTransaction( );
            m_lock.ReleaseWriterLock( );
        }
 
        public void Load()
        { 
            ThrowIfDisposed( ); 

            IDT.TraceVerbose( 
                    TraceCode.StoreLoading,
                    SourceId );

            OnLoad( ); 
            m_isLoaded = true;
        } 
 
        public void Clear()
        { 
            ThrowIfLoaded();

            ThrowIfDisposed();
 
            IDT.TraceVerbose(
                    TraceCode.StoreDeleting, 
                    SourceId ); 

            OnClear(); 
            m_isLoaded = false;
            m_isCleared = true;
        }
 
        public void Close()
        { 
            if( m_isLoaded ) 
            {
                IDT.TraceVerbose( 
                    TraceCode.StoreClosing,
                    SourceId );

                OnClose( ); 
                m_isLoaded = false;
            } 
        } 

        public DataRow GetSingleRow( params QueryParameter[] objectQuery ) 
        {
            return GetSingleRow( QueryDetails.FullRow,objectQuery );
        }
        public DataRow GetSingleRow( QueryDetails details, params QueryParameter[] objectQuery ) 
        {
            IList list = Query( details,objectQuery ); 
 
            if( null == list || 0 == list.Count  )
            { 
                return null;
            }
            else if( list.Count > 1 )
            { 
                throw IDT.ThrowHelperError( new InvalidOperationException(
                            SR.GetString( SR.StoreMoreThanOneRowReturnedInSingleMatchQuery ) ) ); 
            } 
            else
            { 
                return list[ 0 ];
            }
        }
        public IList Query( params QueryParameter[] objectQuery ) 
        {
            return Query( QueryDetails.FullRow, objectQuery ); 
        } 

 
        public IList Query( QueryDetails details, params QueryParameter[] objectQuery )
        {
            ThrowIfDisposed( );
            ThrowIfNotLoaded( ); 

            if( null == objectQuery || 0 == objectQuery.Length  ) 
            { 
                throw IDT.ThrowHelperArgumentNull( "query" );
            } 

            if( !IsValidQueryDetails( details ) )
            {
                throw IDT.ThrowHelperError( new ArgumentException( "details" ) ); 
            }
 
            if( QueryDetails.None == details ) 
            {
                return null; 
            }

            List rows = null;
            LocalIdCollection localIds = null; 
            LocalIdCollection queryIds = null;
            // 
            // Get a Reader lock on the data. 
            //
            bool lockHeld = false; 
            try
            {
                try { }
                finally 
                {
                    m_lock.AcquireReaderLock( 0 ); 
                    lockHeld = true; 
                }
 
                IDT.TraceDebug(
                    "STORE: Begining DataSource query on {0}",
                    SourceId
                    ); 

                IDT.TraceDebug( 
                    "STORE: Query Details\n\t\tDetailLevel:{0}\n\t\tParamCount:{1}\n\t\tPrimaryParameter:{2}", 
                    details.ToString(),
                    objectQuery.Length, 
                    objectQuery[ 0 ].IndexName );
                IDT.TraceDebug(
                    "STORE: Begining Search Process on {0}",
                    SourceId 
                    );
 
                foreach( QueryParameter q in objectQuery ) 
                {
                    queryIds = new LocalIdCollection( ); 


                    //
                    // Special case LocalId.  This means 
                    //  that the exact row id is known, so
                    //  just add all caontained ids to the list. 
                    // 
                    if( "localid" == q.IndexName.ToLower( System.Globalization.CultureInfo.InvariantCulture )  )
                    { 
                        for( int i = 0; i < q.Count; i++ )
                        {
                            for( int j = 0; j < q[ i ].ObjectList.Length; j++ )
                            { 
                                Int32 value = Convert.ToInt32(
                                                q[ i ].ObjectList[ j ], 
                                                    System.Globalization.NumberFormatInfo.InvariantInfo ) ; 

                                queryIds.Add( value ); 
                            }
                        }

 
                    }
                    else 
                    { 
                        //
                        // Perform a match agains the currently collected 
                        // Ids and the current query, if false, no results
                        // matched.
                        //
                        if( !SingleMatch( q, queryIds ) ) 
                        {
                            // 
                            // If we had a failed match, 
                            // ensure that the list of ids is cleared.
                            // 
                            if( null != localIds )
                            {
                                localIds.Clear( );
                            } 
                            break;
                        } 
 
                    }
 
                    //
                    // Perform the AND between the current
                    // results, and the returned results.
                    // 
                    if( null == localIds )
                    { 
                        localIds = queryIds; 
                    }
                    else 
                    {
                        localIds.Filter( queryIds );
                    }
 
                    IDT.TraceDebug(
                            "STORE: {0} matches found for index {1}", 
                            queryIds.Count, 
                            q.IndexName );
                    IDT.TraceDebug( 
                            "STORE: {0} unique matches found as of current",
                            null != localIds ? localIds.Count : 0 );
                }
            } 
            finally
            { 
                if (lockHeld) 
                {
                    m_lock.ReleaseReaderLock( ); 
                }
            }

            IDT.TraceDebug( 
                    "STORE: Search Results: {0} item(s) found.",
                    null != localIds ? localIds.Count : 0 
                    ); 

            IDT.TraceDebug( 
                    "STORE: Search Process Complete on {0}",
                    SourceId
                    );
 
            //
            // If we didn't have any local ids, 
            // then just bail. 
            //
            if( null == localIds || 0 == localIds.Count ) 
            {
                IDT.TraceDebug(
                        "STORE: Query Complete, 0 DataRow(s) returned." );
 
                return null;
            } 
 
            IDT.TraceDebug(
                "STORE: Begining DataCollection Process on {0}", 
                SourceId
                );

            rows = new List( localIds.Count ); 
            foreach( int id in localIds.Keys )
            { 
                IDT.TraceDebug( 
                    "STORE: Collecting data for objectId {0}",
                    id 
                );
                //
                // If a detail level of identifiers is specified,
                //  we don't have to read the row from the data 
                //  buffer, we have all of the information we need.
                // 
                if( QueryDetails.Identifiers == details ) 
                {
                    DataRow row = new DataRow(); 
                    row.LocalId = id;
                    row.SourceId = SourceId;
                    row.InstanceId = InstanceId;
                    rows.Add( row ); 
                }
                else 
                { 
                    //
                    // Read the details of the row from the data source. 
                    //
                    rows.Add( ReadRow( id,details ) );
                }
            } 

            IDT.TraceDebug( 
                    "STORE: DataCollection Process Complete on {0}", 
                    SourceId
                    ); 
            IDT.TraceDebug(
                    "STORE: Query Complete, {0} DataRow(s) returned.",
                    localIds.Count
                    ); 
            return rows;
        } 
 
        //
        // Summary: 
        //  Saves a DataRow to this data source.
        //
        // Remarks:
        //  if the row has a SourceId and InstanceId set, 
        //      it must be the same as the local values.
        // 
        //  This method also updates the LastChange value on the row. 
        //
        // Paramters: 
        //  row:        The data row you would like to save. (see remarks)
        //
        public void Save( DataRow row )
        { 
            ThrowIfDisposed( );
            ThrowIfNotLoaded( ); 
            ThrowIfWriteLockNotHeld( ); 

            if( null == row ) 
            {
                throw IDT.ThrowHelperArgumentNull( "row" );
            }
 
            //
            // If either of these are set, 
            // they must both must match our source info 
            //
            if( !String.IsNullOrEmpty( row.InstanceId ) || 
                !String.IsNullOrEmpty( row.SourceId ) )
            {
                //
                // Note Ordinal will compare the bytes as they are. 
                // This is especially interesting for Unicode Chars.
                // So though the following mean the same linguistically, they will be interpreted as different. 
                // string separated = "\u0061\u030a"; //latin small letter 'a' & ring above 
                // string combined = "\u00e5"; //latin small letter 'a' with ring above
                // [ Using Invariant Culture as opposed Ordinal to will match these. ] 
                //

                if( 0 != string.Compare(
                        row.InstanceId, 
                        InstanceId,
                        StringComparison.Ordinal ) || 
                    0 != string.Compare( 
                        row.SourceId,
                        SourceId, 
                        StringComparison.Ordinal ) )
                {
                    throw IDT.ThrowHelperError( new InvalidOperationException(
                                SR.GetString( SR.StoreRowOwnedByOtherDataSource ) ) ); 
                }
            } 
 
            IDT.TraceDebug(
                    "STORE: Begining Save Operation on {0}", 
                    SourceId );

            row.LastChange = DateTime.Now.ToFileTimeUtc();
 
            //
            // Call the implementers WriteRow 
            // 
            WriteRow( row );
 
            row.InstanceId = InstanceId;
            row.SourceId = SourceId;

            IDT.TraceDebug( 
                    "STORE: Save Operation Complete on {0}",
                    SourceId ); 
 
        }
 

        //
        // Summary:
        //  Deletes a datarow from the data source. 
        //
        // Remarks: 
        //  InstanceId and SourceId must be set to the current members. 
        //
        // Parameters: 
        //  row:        The row you would like to delete.
        //
        public void Delete( DataRow row )
        { 
            ThrowIfDisposed( );
            ThrowIfNotLoaded( ); 
            ThrowIfWriteLockNotHeld( ); 

            if( null == row ) 
            {
                throw IDT.ThrowHelperArgumentNull( "row" );
            }
 
            //
            // If either of these are set, 
            // they must both must match our source info 
            //
            if( null == row.InstanceId || null == row.SourceId ) 
            {
                throw IDT.ThrowHelperError( new InvalidOperationException(
                            SR.GetString( SR.StoreDataSourceRowNotOwned ) ) );
            } 

            // 
            // Note Ordinal will compare the bytes as they are. 
            // This is especially interesting for Unicode Chars.
            // So though the following mean the same linguistically, they will be interpreted as different. 
            // string separated = "\u0061\u030a"; //latin small letter 'a' & ring above
            // string combined = "\u00e5"; //latin small letter 'a' with ring above
            // [ Using Invariant Culture as opposed Ordinal to will match these. ]
            // 

            if( 0 != string.Compare( 
                    row.InstanceId, 
                    InstanceId,
                    StringComparison.Ordinal ) || 
                0 != string.Compare(
                    row.SourceId,
                    SourceId,
                    StringComparison.Ordinal ) ) 
            {
                throw IDT.ThrowHelperError( new InvalidOperationException( 
                                SR.GetString( SR.StoreRowOwnedByOtherDataSource ) ) ); 
            }
 
            IDT.TraceDebug(
                    "STORE: Begining Delete Operation on {0}",
                    SourceId );
 
            //
            // Call Implementers RemoveObject 
            // 
            RemoveObject( row.LocalId );
 
            IDT.TraceDebug(
                    "STORE: Delete Operation Complete on {0}",
                    SourceId );
        } 

 
 
        //
        // Summary: 
        //  Tests a specified QueryDetails value for correctness.
        //
        // Remarks:
        // 
        //  Valid Combos:
        // 
        //   Flags.             Combos 
        //  ------------   ---------------------
        //  Identifiers       1  1  1  1  0 
        //  Header            1  1  1  0  0
        //  DataBlob          1  1  0  0  0
        //  IndexData         1  0  0  0  0
        // 
        // Parameters:
        //  details:        The QueryDetails value to test. 
        // 
        // Returns:
        //  boolean indicated that the value is valid. 
        //
        protected internal virtual bool IsValidQueryDetails( QueryDetails details )
        {
            if( QueryDetails.IndexData == ( details & QueryDetails.IndexData ) ) 
            {
                return QueryDetails.FullRowAndIndexes == ( details & QueryDetails.FullRowAndIndexes ); 
            } 
            else if( QueryDetails.DataBlob == ( details & QueryDetails.DataBlob  ) )
            { 
                return QueryDetails.FullRow == ( details & QueryDetails.FullRow );
            }
            else if( QueryDetails.Header == ( details & QueryDetails.Header ) )
            { 
                return QueryDetails.FullHeader == ( details & QueryDetails.FullHeader);
            } 
            else if( QueryDetails.Identifiers == ( details & QueryDetails.Identifiers ) ) 
            {
                return QueryDetails.Identifiers == ( details & QueryDetails.Identifiers ); 
            }
            else
            {
                return ( QueryDetails.None == details ); 
            }
        } 
 
        protected internal virtual void OnBeginTransaction()
        { 
            ThrowIfDisposed( );
        }
        protected internal virtual void OnCommitTransaction()
        { 
            ThrowIfDisposed( );
        } 
        protected internal virtual void OnRollbackTransaction() 
        {
            ThrowIfDisposed( ); 
        }
        protected internal virtual void OnLoad()
        {
            ThrowIfDisposed( ); 
        }
        protected internal virtual void OnClose() 
        { 
            ThrowIfDisposed( );
        } 
        protected internal virtual void OnClear()
        {
            ThrowIfDisposed();
        } 
        protected internal virtual void OnDispose()
        { 
 
        }
 
        protected internal abstract void WriteRow( DataRow row );
        protected internal abstract void RemoveObject( Int32 id );
        protected internal abstract DataRow ReadRow( Int32 localId,QueryDetails details );
        protected internal abstract bool SingleMatch( QueryParameter match, LocalIdCollection localIds ); 

        void IDisposable.Dispose() 
        { 
            OnDispose( );
            m_isDisposed = true; 
        }

        protected internal void ThrowIfWriteLockNotHeld()
        { 
            if( !m_lock.IsWriterLockHeld )
            { 
                throw IDT.ThrowHelperError( new InvalidOperationException( 
                            SR.GetString( SR.StoreDataSourceWriteLockNotHeld ) ) );
            } 
        }
        protected internal void ThrowIfWriteLockHeld()
        {
            if( m_lock.IsWriterLockHeld ) 
            {
                throw IDT.ThrowHelperError( new InvalidOperationException( 
                            SR.GetString( SR.StoreProcessingTransaction ) ) ); 
            }
        } 
        protected internal void ThrowIfNotLoaded()
        {
            if( !m_isLoaded )
            { 
                throw IDT.ThrowHelperError( new ObjectDisposedException( "DataSource" ) );
            } 
        } 
        protected internal void ThrowIfLoaded()
        { 
            if( m_isLoaded )
            {
                throw IDT.ThrowHelperError( new InvalidOperationException(
                            SR.GetString( SR.StoreIsAlreadyLoaded ) ) ); 
            }
        } 
        protected internal void ThrowIfDisposed() 
        {
            if( m_isDisposed ) 
            {
                throw IDT.ThrowHelperError( new ObjectDisposedException( "DataSource" ) );
            }
        } 

 
        // 
        // Summary: Build a QueryParamter for the ix_objecttype index, that contains all
        // of the values other than unknown. This is used in the deletion of all 
        // the relevant store data. UserPreference is left in the store to preserve
        // the UI size related information (will be shortly).
        //
        public static QueryParameter CreateDeleteStoreTypeQuery() 
        {
            QueryParameter deleteStoreQuery = new QueryParameter( SecondaryIndexDefinition.ObjectTypeIndex ); 
            Array objectTypes = Enum.GetValues( typeof( StorableObjectType ) ); 

            foreach( Int32 type in objectTypes ) 
            {
                if ( (Int32) StorableObjectType.Unknown != type )
                {
                    deleteStoreQuery.AddMatch( type ); 
                }
            } 
            return deleteStoreQuery; 
        }
    } 

    internal delegate int MergeConflictCallback( DataRow local, DataRow incomingData );
}

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

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