DataSetHelper Class that I am using

Previously I’ve posted a few Helper Classes . This post describes  DataSetHelper class, that mostly based on series of MSDN articles. However I did some modifications(e.g see posts DataSetHelper.SelectDistinct method for multiple columns and  “Handling missing source columns in DataSetHelper.InsertInto method” )

using System;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Collections;
using Microsoft.ApplicationBlocks.Data;
using System.Collections.Generic;
 
namespace FSHelperLib
{
      ///<summary>
      /// Created based on HOW TO: Implement a DataSet SELECT INTO Helper Class in Visual C# .NET
      ///</summary>
      public class DataSetHelper
      {
            public DataSet m_ds;
 
            public DataSetHelper(ref DataSet DataSet)
            {
                  m_ds = DataSet;
            }
            public DataSetHelper()
            {
                  m_ds = null;
            }
        private List<FieldInfo> m_FieldInfo;//System.Collections.ArrayList
        private string m_FieldList;
 
            public class FieldInfo
            {
                  public string RelationName;
                  public string FieldName;      //source table field name
                  public string FieldAlias;     //destination table field name
                  //public string Aggregate;
            }
            #region “private Helper methods”
            private void ParseFieldList(string FieldList, bool AllowRelation)
            {
                  /*
                   * This code parses FieldList into FieldInfo objects and then
                   * adds them to the m_FieldInfo private member.
                   *
                   * FieldList syntax: [relationname.]fieldname[ alias], …
                  */
                  if (m_FieldList == FieldList) return;
            m_FieldInfo = new List<FieldInfo>();// System.Collections.ArrayList();
                  m_FieldList = FieldList;
            m_FieldInfo=ParseToFieldInfoList(FieldList, AllowRelation);
            }
///<summary>
        ///              * FieldList syntax: [relationname.]fieldname[ [AS] alias], …
///</summary>
///<param name=”FieldList”></param>
///<param name=”AllowRelation”></param>
///<returns></returns>
        public static List<FieldInfo> ParseToFieldInfoList(string FieldList, bool AllowRelation)
        {
            // Doesn’t support parsing comticate function like the following “, Left(ma_compdate,10) as Closed,”
            List<FieldInfo> lstFieldInfo = new List<FieldInfo>();
            FieldInfo Field; string[] FieldParts;
            string[] Fields = FieldList.Split(‘,’);
            int i;
            for (i = 0; i <= Fields.Length – 1; i++)
            {
                Field = new FieldInfo();
                //Parse FieldAlias.
                FieldParts = Fields[i].Trim().Split(new char[] { ‘ ‘ }, StringSplitOptions.RemoveEmptyEntries);
                switch (FieldParts.Length)
                {
                    case 1:
                        //to be set at the end of the loop
                        break;
                    case 2:
                        Field.FieldAlias = FieldParts[1];
                        break;
                    default: //if more than 2 , it shoud ended with ” AS Alias “
                        if (FieldParts[FieldParts.Length-2].ToUpper().Trim() == “AS”)
                            Field.FieldAlias = FieldParts[FieldParts.Length – 1];
                        else
                            throw new Exception(“Too many parts in field definition: ‘” + Fields[i] + “‘.”);
                        break;
                }
                if (FieldParts.Length <= 3)
                {                    //Parse FieldName and RelationName.
                    FieldParts = FieldParts[0].Split(‘.’);
                    switch (FieldParts.Length)
                    {
                        case 1:
                            Field.FieldName = FieldParts[0];
                            break;
                        case 2:
                            if (AllowRelation == false)
                                throw new Exception(“Relation specifiers not permitted in field list: ‘” + Fields[i] + “‘.”);
                            Field.RelationName = FieldParts[0].Trim();
                            Field.FieldName = FieldParts[1].Trim();
                            break;
                        default:
                            throw new Exception(“Invalid field definition: “ + Fields[i] + “‘.”);
                    }
                }
                else //In case of calculated field (e.g. cl_Addr1 + cl_Addr2 + cl_Addr3 as Address)
                {
                  Field.FieldName= StringHelper.LeftBeforeLast(Fields[i].Trim().ToUpper() , ” AS “);//not always reliable
                }
                if (Field.FieldAlias == null)
                    Field.FieldAlias = Field.FieldName;
                lstFieldInfo.Add(Field);
            }
            return lstFieldInfo;
        }
            #endregion //”private Helper methods”
           
            #region “CreateTable,INSERTInto and SelectINTO”
            ///<summary>
            /// This code creates a DataTable and creates the fields (not specified types) in the
            ///   order that is specified in the FieldList.
            /// See Also CreateTable overload with SourceTable parameter />
            ///</summary>
            ///<example>
            /// Sample of call
            ///<code>dt = dsHelper.CreateTable(“TestTable”, “FirstName FName,LastName LName,BirthDate”);
            ///</code></example>
            public DataTable CreateTable(string TableName, string FieldList)
            {
                  /*
                  */
                  DataTable dt;
                  {
                        dt = new DataTable(TableName);
                        ParseFieldList(FieldList,false);
                        DataColumn dc;
                        foreach (FieldInfo Field in m_FieldInfo)
                        {
                              dc = new DataColumn(Field.FieldName);//not specified types
                              dt.Columns.Add(Field.FieldAlias, dc.DataType);
                        }
                  }
                  if (m_ds!=null)
                        m_ds.Tables.Add(dt);
                  return dt;
            }
            ///<summary>
            /// This code creates a DataTable by using the SourceTable as a template and creates the fields in the
            ///   order that is specified in the FieldList. If the FieldList is blank, the code uses DataTable.Clone().
            /// See Also CreateTable overload without SourceTable parameter />
            ///</summary>
            ///<example>
            /// Sample of call
            ///<code>dt = dsHelper.CreateTable(“TestTable”, ds.Tables[“Employees”], “FirstName FName,LastName LName,BirthDate”);
            ///</code></example>
            public DataTable CreateTable(string TableName, DataTable SourceTable, string FieldList)
            {
                  DataTable dt;
            if (FieldList.Trim() == “”)
            {
                dt = SourceTable.Clone();
                dt.TableName = TableName;
            }
            else
            {
                dt = new DataTable(TableName);
                ParseFieldList(FieldList, false);//not static
                DataColumn dc;
                foreach (FieldInfo Field in m_FieldInfo)
                {
                    dc = SourceTable.Columns[Field.FieldName];
                    dt.Columns.Add(Field.FieldAlias, dc.DataType);
                }
            }
            if (m_ds != null)
                        m_ds.Tables.Add(dt);
                  return dt;
            }
            ///<summary>
            /// Sample of call
            /// dsHelper.InsertInto(ds.Tables[“TestTable”], ds.Tables[“Employees”], “FirstName FName,LastName LName,BirthDate”, “EmployeeID&lt;5”, “BirthDate”) ;
            ///</summary>
            public void InsertInto(DataTable DestTable, DataTable SourceTable,
                  string FieldList, string RowFilter, string Sort)
            {
                  //
                  // This code copies the selected rows and columns from SourceTable and inserts them into DestTable.
                  //
                  ParseFieldList(FieldList, false);
                  DataRow[] Rows = SourceTable.Select(RowFilter, Sort);
                  DataRow DestRow;
                  foreach(DataRow SourceRow in Rows)
                  {
                        DestRow = DestTable.NewRow();
                        if (DataHelper.IsNullOrEmpty(FieldList))
                        {
                    foreach (DataColumn dc in DestRow.Table.Columns)
                    {
                        if (dc.Expression == “”)
                        {
                            if (SourceTable.Columns.Contains(dc.ColumnName))//source can miss some target columns
                                DestRow[dc] = SourceRow[dc.ColumnName];
                            else
                                DebugHelper.LineWithTrace(“The column is missing in the source:” + dc.ColumnName);
                        }
                    }
                        }
                        else
                        {
                              foreach(FieldInfo Field in m_FieldInfo)
                              {
                                    DestRow[Field.FieldAlias] = SourceRow[Field.FieldName];
                              }
                        }
                        DestTable.Rows.Add(DestRow);
                  }
            }
            //MNF 10/9/2004
            ///<summary>
            /// Sample of call
            /// dsHelper.ImportInto(sTestTable, rSourceRow) ;
            ///</summary>
            ///<returns>true if inserted, false if primary key is already in the table</returns>
            public bool ImportInto(string sDestTableName, DataRow rSourceRow)
            {
                  //
                  // This code copies the specified row and inserts it into DestTable.
                  //
                 
                  Debug.Assert(m_ds!=null);
                  DataTable tbl=m_ds.Tables[sDestTableName];
                  if (tbl==null)
                  { tbl=CreateTable(sDestTableName,rSourceRow.Table,“”);
                  }
            bool bRet=RowInTableExists( tbl, rSourceRow );
                  //DataColumn[] colKeys=tbl.PrimaryKey;
            //object[] keyValues=PrimaryKeyValues(rSourceRow);
 
//                if (tbl.Rows.Find(keyValues)==null)
                  if (bRet==false)
                  {
                        tbl.ImportRow(rSourceRow); //TODO can be change to use foreach as in InsertInto
//                      bRet=true;
                  }
            //else //already exists
            //    bRet=false;
                  return bRet;
            }
           
            ///<summary>
            /// Sample of call
            /// dt = dsHelper.SelectInto(“TestTable”, ds.Tables[“Employees”], “FirstName FName,LastName LName,BirthDate”, “EmployeeID&lt;5”, “BirthDate”) ;
            ///</summary>
            public DataTable SelectInto(string TableName, DataTable SourceTable,
                  string FieldList, string RowFilter, string Sort)
            {
                  /*
                   * This code selects values that are sorted and filtered from one DataTable into another.
                   * The FieldList specifies which fields are to be copied.
                  */
                  DataTable dt = CreateTable(TableName, SourceTable, FieldList);
                  InsertInto(dt, SourceTable, FieldList, RowFilter, Sort);
                  return dt;   
            }
            #region “SelectDistinct”
            //It is used to compare field values (including NULL).
            private static bool ColumnEqual(object A, object B)
            {
 
                  // Compares two values to see if they are equal. Also compares DBNULL.Value.
                  // Note: If your DataTable contains object fields, then you must extend this
                  // function to handle them in a meaningful way if you intend to group on them.
 
                  if ( A == DBNull.Value && B == DBNull.Value ) // both are DBNull.Value
                        return true;
                  if ( A == DBNull.Value || B == DBNull.Value ) // only one is DBNull.Value
                        return false;
                  return ( A.Equals(B) ); // value type standard comparison
            }
                             
 
      //    2. Add the following Public method to the class definition. This method copies unique values of the field that you select into a new DataTable. If the field contains NULL values, a record in the destination table will also contain NULL values.
            public DataTable SelectDistinct(string TableName, DataTable SourceTable, string FieldName)
            {
            DataTable dt = SelectDistinct(SourceTable, FieldName);
            dt.TableName = TableName;
                  if (m_ds != null)
                        m_ds.Tables.Add(dt);
                  return dt;
            }
 
        public static DataTable SelectDistinct(DataTable SourceTable, string FieldName)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add(FieldName, SourceTable.Columns[FieldName].DataType);
 
            object LastValue = null;
            foreach (DataRow dr in SourceTable.Select(“”, FieldName))
            {
                if (LastValue == null || !(ColumnEqual(LastValue, dr[FieldName])))
                {
                    LastValue = dr[FieldName];
                    dt.Rows.Add(new object[] { LastValue });
                }
            }
            return dt;
        }
            public static DataTable SelectDistinct( DataTable SourceTable, string[] FieldNames)
            {// select distinct on multiple fields.
//From: Nageswara Reddy http://www.dotnet247.com/247reference/msgs/43/218182.aspx
            FieldNames = StringArrayHelper.ToLower(FieldNames);
            DataTable DistinctTable = SourceTable.Clone();
                  DataColumn [] constraintColumns = new DataColumn[FieldNames.Length];
            int nFound=0;
                  for (int i =0 ; i< DistinctTable.Columns.Count ; i++)
            {
                if (Array.IndexOf(FieldNames, DistinctTable.Columns[i].ColumnName.ToLower()) >= 0)
                {
                    if (nFound >= FieldNames.Length)
                    {
                        throw new ApplicationException(“Too many fields are similar to passed FieldNames “ + FieldNames.ToString());
                    }
                    constraintColumns[nFound++] = DistinctTable.Columns[i];
                }
                  }
            //Report if passed field names are not found in the table
            if (nFound < FieldNames.Length)
            {
                throw new ApplicationException(“Some of fields “ + FieldNames.ToString() + ” not found in the database”);
            }
                  UniqueConstraint _UniqueConstraint = new UniqueConstraint(constraintColumns);
                  DistinctTable.Constraints.Add(_UniqueConstraint);
 
                  for (int i =0 ; i< SourceTable.Rows.Count ; i++)
                  {
                        try
                        {
                              DistinctTable.ImportRow(SourceTable.Rows[i]);
                        }
                        catch(Exception ex)
                        { // Keep quite
                              Debug.WriteLine(ex.ToString());
                        }
                  }
                  return DistinctTable;
            }
      #endregion “SelectDistinct”
 
 
            //MNF 10/12/2004
            ///<summary>
            /// Merge consider merged items as new
        /// dsHelper.MergeAsNew(tblSource,      MissingSchemaAction.AddWithKey) ;
            ///</summary>
            ///<remarks> function clones source table to modify status of records as add </remarks>       
            ///<returns>true if inserted, false if primary key is already in the table</returns>
            public DataSet MergeAsNew( DataTable tblSource, MissingSchemaAction missingSchemaAction)
            {
                  Debug.Assert(m_ds!=null);
                  DataTable tblClone=tblSource.Clone();
                  InsertInto(tblClone, tblSource, “”,“”,“”);
                  bool preserveChanges=true;//hardcoded
                  m_ds.Merge(tblClone, preserveChanges,missingSchemaAction);
                  return m_ds;
            }
        ///<summary>
        /// The function expects that original table exist in the dataset.
        /// New records from tblToAdd will have DataRowState.Added and existing records will have DataRowState.Modified
        /// dsHelper.MergeAsNewOrModified(tblToAdd,   MissingSchemaAction) ;
        ///</summary>
        ///<remarks> function clones source table to modify status of records as add </remarks>       
        ///<returns>modified dataset
        /// Newly added rows are marked as insertions, and changes to existing rows are marked as modifications.
        ///</returns>
        public DataSet MergeAsNewOrModified(DataTable tblToAdd,MissingSchemaAction missingSchemaAction)
        {
                  Debug.Assert(m_ds!=null);
            string sTableName = tblToAdd.TableName;
            if (m_ds.Tables[sTableName] == null)
            {
                MergeAsNew(tblToAdd, missingSchemaAction);
            }
            else
            {
                DataTable tblOrig = m_ds.Tables[sTableName];
                foreach (DataRow rowToAdd in tblToAdd.Rows)
                      {
                   //Finds and updates a specific row. If no matching row is found, a new row is created using the given values.
                  DataRow row= DataHelper.LoadDataRow(tblOrig, rowToAdd, true);
                      }
            }
            return m_ds;
        }
        #endregion //”CreateTable,INSERTInto and SelectINTO”
            //MNF 10/9/2004
            ///<summary>
            /// Sample of call
            /// dsHelper.RemoveFromTable(sTestTable, rSourceRow) ;
            ///</summary>
            ///<returns>true if delete, false if primary key is not in the table</returns>
            public bool RemoveFromTable(string sTableName, DataRow rSourceRow)
            {
                  Debug.Assert(m_ds!=null);
                  DataTable tbl=m_ds.Tables[sTableName];
                  if (tbl==null)
                  {
                              return false;
                  }
            //bool bRet=RowInTableExists( tbl, rSourceRow );
            //object[] keyValues=PrimaryKeyValues(rSourceRow);
            return RemoveFromTable( tbl,rSourceRow);
            }
        ///<summary>
        ///
        ///</summary>
        ///<param name=”tbl”></param>
        ///<param name=”rSourceRow”></param>
        ///<returns>true if delete, false if primary key is not in the table</returns>
        public static bool RemoveFromTable(DataTable tbl,DataRow rSourceRow )
        {
            DataRow row = FindRow(tbl, rSourceRow);
            if (null != row)
            {
                tbl.Rows.Remove(row);
                //bRet=true;
            }
            //else //not exist
            //    bRet=false;
            return (null != row);
        }
        ///<summary>
        /// Remove Rows with the specified state, e.g during refresh it may be required to delete Unchanged rows
        ///</summary>
        ///<param name=”sTableName”></param>
        ///<param name=”RowState”></param>
        ///<returns></returns>
        public static bool RemoveRowsFromTable( DataTable tbl, DataRowState RowState)
        {
            if (tbl == null) { throw new ArgumentNullException(“DataTable tbl”); }
            foreach (DataRow row in tbl.Rows)
            {
              if(row.RowState==RowState)
              {
                  row.Delete();  
              }
            }
            return true;
        }
 
        ///<summary>
        /// return table(not attached to dataset) with row copies with specified keys 
///</summary>
///<param name=”tbl”></param>
        ///<param name=”keys”>if Keys is null,return copy of full table not attached to dataset</param>
///<returns></returns>
        public static DataTable FilterTableByKeys(DataTable tbl, string[] keys)
        {
            if (tbl == null) { throw new ArgumentNullException(“DataTable tbl”); }
            if (keys == null) { throw new ArgumentNullException(“string[] keys”); }
            DataTable newTbl = null;
            if (keys != null)
            {
                newTbl = tbl.Clone();
                foreach (string key in keys)
                {
                    DataRow row = tbl.Rows.Find(key);
                    if (null != row)
                        newTbl.ImportRow(row);
                    else
                    {
                        DebugHelper.TracedLine(“key not found” + key);
                        Debug.Assert(false, “key not found” + key);
                    }
                }
            }
            return newTbl;
        }
        ///<summary>
        /// return table(not attached to dataset) with row copies with specified keys 
        ///</summary>
        ///<param name=”tbl”>Not Null</param>
        ///<param name=”lstKeys”>Not Null</param>
        ///<returns></returns>
        public static DataTable FilterTableByKeys(DataTable tbl, List<string> lstKeys)
        {
            string[] keys = null;
            if (null!=lstKeys)
            {
                keys = lstKeys.ToArray();
            }
            return FilterTableByKeys(tbl, keys);
        }
        ///<summary>
        /// Remove all rows that have keys different to listed in lstKeys
        ///</summary>
        ///<param name=”tbl”></param>
        ///<param name=”lstKeys”>if lstKeys is null, the unchanged table is returned</param>
        ///<returns></returns>
        public static DataTable ReplaceTableWithFilteredByKeys(DataTable tbl, List<string> lstKeys)
        {
            if (null != lstKeys)
            {
                DataTable tblNew = FilterTableByKeys(tbl, lstKeys);
                tbl.Clear();
               tbl.Merge(tblNew);
            }
            return tbl;
        }
 
        //MNF 21/10/2004
            ///<summary>
            /// Sample of call
            /// dsHelper.FindInTable(sTestTable, rSourceRow) ;
            ///</summary>
            ///<returns>true if found, false if primary key is not in the table</returns>
            public bool FindInTable(string sTableName, DataRow rSourceRow)
            {
                  //bool bRet;
                  Debug.Assert(m_ds!=null);
                  DataTable tbl=m_ds.Tables[sTableName];
                  if (tbl==null)
                  {
                        return false;
                  }
            return RowInTableExists( tbl, rSourceRow);
            }
        public static bool RowInTableExists(DataTable tbl,DataRow rSourceRow )
        {
            //    bool bRet;
            if(tbl==null){    throw new ArgumentNullException(“tbl”);}
            DataRow row = FindRow(tbl, rSourceRow);
            return (null!=row) ;
        }
        public static DataRow FindRow(DataTable tbl, DataRow rSourceRow)
        {
           // bool bRet;
            object[] keyValues = PrimaryKeyValues(rSourceRow);
            return tbl.Rows.Find(keyValues);
 
        }
 
            ///<summary>
            /// Sample of call
            /// dsHelper.InsertInto(sTestTable, ds.Tables[“Employees”], “FirstName FName,LastName LName,BirthDate”, “EmployeeID<5″, “BirthDate”) ;
            /// </summary>
            /// <returns>true if inserted, false if primary key is already in the table</returns>
            public static object[] PrimaryKeyValues(DataRow rSourceRow)
            {
                  DataColumn[] colKeys=rSourceRow.Table.PrimaryKey;
                  ArrayList values = new ArrayList();
                  foreach(DataColumn dc in colKeys)
                  {
                              values.Add( rSourceRow[dc.ColumnName]);
                  }
                  return values.ToArray();;
            }
 
            ///<summary>
            /// Sample of call
            /// dsHelper.InsertInto(sTestTable, ds.Tables[“Employees”], “FirstName FName,LastName LName,BirthDate”, “EmployeeID<5″, “BirthDate”) ;
            /// </summary>
            /// <returns>true if inserted, false if primary key is already in the table</returns>
            public static bool IsIndexValid(DataTable tbl,int RowIndex)
            {
                  return ((RowIndex>=0) && (RowIndex< tbl.Rows.Count) ) ;
            }
            public static bool HasChanges(DataTable tbl)
            { //from http://www.groupsrv.com/dotnet/viewtopic.php?t=30224&view=previous
                  //thisDataSet.Tables[tableName]
                  foreach (DataRow dr in tbl.Rows) 
                  {
                        if (dr.RowState != DataRowState.Unchanged)
                              return true;
                  }
                  return false;
            }
 
 
            //use SqlCommandBuilder
        public static DataTable UpdateDataSet(string connString, DataSet ds, string sSelectSQL, string TableName)
            { return UpdateDataSet( connString, ds, sSelectSQL, TableName,false);
            }
            public static DataTable UpdateDataSet(string connString, DataSet ds,string sSelectSQL,string TableName,bool ContinueUpdateOnError )
            {
                  //SqlCommandBuilder commandBuilder;
            DataTable dt = null;
            if (null == TableName)
            {
                dt = ds.Tables[0];//assume that only the first table(with defalt name “Table”) is updated
            }
            else
            {
                dt = ds.Tables[TableName];
            }
            DataTable dtChanges = dt.GetChanges();
                  if (!(dtChanges == null))
                  {
                dtChanges=UpdateDataTable(connString, dt, sSelectSQL, ContinueUpdateOnError);
                //SqlDataAdapter da = new SqlDataAdapter(sSelectSQL, connString);
                //commandBuilder = new SqlCommandBuilder(da);
                //commandBuilder.QuotePrefix =”[“;//TODO for all SqlCommandBuilder
                //commandBuilder.QuoteSuffix =”]”;
                //da.ContinueUpdateOnError = ContinueUpdateOnError;
                //DebugHelper.PrintSqlCommandBuilder(commandBuilder,”UpdateDataSet:”);
                //if (null==TableName)
                //{
                //    da.Update(dsChanges);//assume that only the first table(with defalt name “Table”) is updated
                //    ds.AcceptChanges();
                //}
                //else
                //{
                //    da.Update( dsChanges, TableName);
                //    ds.Tables[TableName].AcceptChanges();
                //    //                                    LogErrors(dsChanges, “UpdateKeywordTables ” + tbl + ” SQL=” + sSQL);
                //}
                  }
            return dtChanges; //important GetErrors
        }
        ///<summary>
        ///
        ///</summary>
        ///<param name=”connString”></param>
        ///<param name=”dt”></param>
        ///<param name=”sSelectSQL”></param>
        ///<param name=”ContinueUpdateOnError”></param>
        ///<returns>can return null, if no cahnges</returns>
        public static DataTable UpdateDataTable(string connString, DataTable dt, string sSelectSQL, bool ContinueUpdateOnError)
        {
            DataTable dtChanges = dt.GetChanges();
            if (!(dtChanges == null))
            {
                SqlDataAdapter da = CreateSqlDataAdapterWithBuilder(sSelectSQL, connString, ContinueUpdateOnError);
                da.Update(dtChanges);//assume that only the first table(with defalt name “Table”) is updated
                dtChanges.AcceptChanges();//not sure, it is required
                dt.AcceptChanges(); //alternatively dt.Merge(dtChanges) 5/4/2006
                //                                    LogErrors(dsChanges, “UpdateKeywordTables ” + tbl + ” SQL=” + sSQL);
            }
            return dtChanges;
        }
        public static SqlDataAdapter CreateSqlDataAdapterWithBuilder(string sSelectSQL, string connString, bool ContinueUpdateOnError)
        {
            SqlCommandBuilder commandBuilder;
            SqlDataAdapter da = new SqlDataAdapter(sSelectSQL, connString);
            commandBuilder = new SqlCommandBuilder(da);
            commandBuilder.QuotePrefix = “[“;//TODO for all SqlCommandBuilder
            commandBuilder.QuoteSuffix = “]”;
            da.ContinueUpdateOnError = ContinueUpdateOnError;
            DebugHelper.PrintSqlCommandBuilder(commandBuilder, “UpdateDataSet:”);
            return da;
        }
 
        #region “DataView operations”  
 
            public static DataTable CreateTable(DataView vwSource)
            {
                  // short circuiting out here
                  int nRowCount = vwSource.Count;
                  if (0 == nRowCount) return null;
                  DataTable tableNew = vwSource.Table.Clone();// clone the schema
                  // copy the values to the new table
                  foreach(DataRowView rv in vwSource)
                  {
                     tableNew.ImportRow(rv.Row);
                  }
                  return tableNew;
            }
        public static string SqlTableForNewRows(string TableName)
        {
            // short circuiting out here
            string sSQL = “Select * From “ + TableName + ” where 0=1″;
            return sSQL;
        }
        public static DataTable OpenTableForNewRows(string TableName,string connString)
        {
            // short circuiting out here
            string sSQL = SqlTableForNewRows(TableName );
            return ExecuteTable(connString, CommandType.Text, sSQL);
            //DataSet ds = SqlHelper.ExecuteDataset(connString, CommandType.Text, sSQL);
            //DataTable tableNew = ds.Tables[0];
            //return tableNew;
        }
        public static DataTable ExecuteTable(string connectionString, CommandType commandType, string commandText)
        {
            DataSet ds = SqlHelper.ExecuteDataset(connectionString, commandType, commandText);
            DataTable tableFirst = ds.Tables[0];
            return tableFirst;
        }
        public static void Delete(DataView view, int startRecord, int maxRecords)
            {
                  view.RowStateFilter = DataViewRowState.CurrentRows | DataViewRowState.Deleted;
                  int nLastRecord = startRecord+ maxRecords – 1;
                  for (int num1 = startRecord; num1 <= nLastRecord; num1++)
            {
                if (num1<view.Count)//5/4/2006
                {
                              view[num1].Delete();
                }
            }
                  view.Table.AcceptChanges();
            }
        public static DataView CloneDataView(DataView vwSource,string newSort)
        {
            return new DataView(vwSource.Table ,vwSource.RowFilter,newSort,vwSource.RowStateFilter) ;
        }
        #endregion “DataView operations”
 
    }//public class DataSetHelper
 
}//namespace