[dba-VB] ADO.Net

Shamil Salakhetdinov shamil at smsconsulting.spb.ru
Sat Apr 26 17:39:45 CDT 2008


Hi John,

Additionally to the below e-mail - you can consider using SQLDataReader to
get data records batches as in this below example, then build parsed names'
arrays together with ids, then Join() these arrays into strings and pass
these strings as parameters to SPs, which will make actual updates by
parsing strings into dynamic update sqls or something like that - T-SQL
parsing functions are reasonably quick, or you can even consider managed SPs
to parse the strings on server side and perform the updates...

...but that latter could be an overkill giving very little gains because
.NET framework's communication with native MS SQL provider when using plain
simple C#/VB.NET is very effective I have heard...

..maybe you can just process your data and generate and run update temp SPs
to have update T-SQL statements batched into such temp SPs - that could give
you (much) quicker updates...

...etc...

--
Shamil

-----Original Message-----
From: dba-vb-bounces at databaseadvisors.com
[mailto:dba-vb-bounces at databaseadvisors.com] On Behalf Of Shamil
Salakhetdinov
Sent: Sunday, April 27, 2008 2:13 AM
To: 'Discussion concerning Visual Basic and related programming issues.'
Subject: Re: [dba-VB] ADO.Net

Hi John,

Try to use SqlDataReader and custom classes as in the sample code below
(sorry C# is used - real pleasure to use C# is also coming from the fact
that you can copy and paste code and do not care about line warps because
even "screwed by e-mail" code should be compiled well)....

...using ADO.NET datasets and bulk update will anyway result in a series of
updates on SQL server side therefore custom on-the-fly built sql updates or
calls to update SPs should work as quick as ADO.NET DataSets' batch
update...

...etc...

...as you can see my sample did update 25000 records in ~10 seconds - and
this only for starters - if that approach will work reasonably well for you
then the next step could be to introduce multi-threading etc...

...note also how MS SQL 2005's paging feature is used to get record's
batches...


using System;
using System.Collections.Generic;
using System.Data.SqlClient;

namespace ORS_TDD_Console
{

    public class DataItem
    {
        public int ID;
        public string Name;

        public DataItem(int id, string name)
        {
            ID = id; Name = name;
        }

        public string ParsedName
        {
            get
            {
                return Name; // just for testing purposes
                             // return real parsed name here
            }
        }
    }

    public class DataProcessor
    {
        private const string COUNT_SQL = "select count(*) from
zsysUserSessionTrace";
        private const string PAGED_SELECT_SQL = 
            "SELECT * from " +
            "(" +
            "    select " +
            "       Cast(ROW_NUMBER() over (ORDER BY [UserSessionTraceId])
as int) as RowNum, " +
		    "        UserSessionTraceId, " +
		    "        HostAddress, " +
		    "        UserBrowser " +
	        "    from zsysUserSessionTrace " +
            ") s " +
            "where s.RowNum between {0} and {1}";
        private const string UPDATE_SQL = "update zsysUserSessionTrace set
UserBrowser = '{0}' where UserSessionTraceId = {1}";

        private const int DEFAULT_BATCH_SIZE = 1000;

        private int _totalCount = -1;
        public int TotalCount { get { return _totalCount; } }

        private int _currentBatchStartRowNum = 0;
        private int _batchSize = 0;

        private string _connectionString;
        public DataProcessor(string connectionString)
        {
            initialize(connectionString, DEFAULT_BATCH_SIZE);
        }
        public DataProcessor(string connectionString, int batchSize)
        {
            initialize(connectionString, batchSize);
        }
        private void initialize(string connectionString, int batchSize)
        {

            _batchSize = batchSize;
           _currentBatchStartRowNum = 1;
           _connectionString = connectionString;

            using (System.Data.SqlClient.SqlConnection cnn = new
System.Data.SqlClient.SqlConnection(connectionString))
            {
                cnn.Open();

                System.Data.SqlClient.SqlCommand cmd = cnn.CreateCommand();
                cmd.CommandText = COUNT_SQL;
                cmd.CommandType = System.Data.CommandType.Text;

                _totalCount = (int)cmd.ExecuteScalar(); 
            }
        }

        public bool HasData
        {
            get
            {
                return (TotalCount > 0 && _currentBatchStartRowNum <
TotalCount);
            }
        }

        public List<DataItem> GetData()
        {
            using (System.Data.SqlClient.SqlConnection cnn = new
System.Data.SqlClient.SqlConnection(_connectionString))
            {
                cnn.Open();

                System.Data.SqlClient.SqlCommand cmd = cnn.CreateCommand();
                string sql = string.Format(PAGED_SELECT_SQL,
_currentBatchStartRowNum, _currentBatchStartRowNum + _batchSize);
                cmd.CommandText = sql;
                cmd.CommandType = System.Data.CommandType.Text;
                _currentBatchStartRowNum += _batchSize + 1;
                System.Data.SqlClient.SqlDataReader rdr = cmd.ExecuteReader(
System.Data.CommandBehavior.SequentialAccess);

                List<DataItem> list = new List<DataItem>();
                while (rdr.Read())
                {
                    list.Add (new DataItem((int)rdr[1], (string)rdr[3])); 
                }
                return list;
            }
        }

        public int Update(DataItem item)
        {
            using (System.Data.SqlClient.SqlConnection cnn = new
System.Data.SqlClient.SqlConnection(_connectionString))
            {
                cnn.Open();

                System.Data.SqlClient.SqlCommand cmd = cnn.CreateCommand();
                string sql = string.Format(UPDATE_SQL, item.ParsedName,
item.ID );
                cmd.CommandText = sql;
                cmd.CommandType = System.Data.CommandType.Text;
                return cmd.ExecuteNonQuery(); 
            }
        }
    }


    public class A_MainEntry
    {
        //27.04.2008 1:53:30
        //Count(*) = 25045
        //Counter = 25045
        //27.04.2008 1:53:40

        public static void Main()
        {
            int count = 0;
            try
            {
                //+ customize - set your connection string here
                string connectionString =
AppConfigManager.DefaultConnectionString;
                //-

                Console.WriteLine(DateTime.Now);
                DataProcessor p = new DataProcessor(connectionString);
                while (p.HasData)
                {
                    List <DataItem> list = p.GetData();
                    foreach (DataItem item in list)
                    {
                        p.Update(item);
                        count++;
                    }
                }
                Console.WriteLine("Count(*) = {0}", p.TotalCount);
                Console.WriteLine("Counter = {0}", count);
                Console.WriteLine(DateTime.Now);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }       
        
    }
}

-----Original Message-----
From: dba-vb-bounces at databaseadvisors.com
[mailto:dba-vb-bounces at databaseadvisors.com] On Behalf Of jwcolby
Sent: Saturday, April 26, 2008 11:26 PM
To: VBA
Subject: [dba-VB] ADO.Net

I have been setting up an application to read a block of records, 
perhaps 10K or something.

<<< the rest trimmed to get message through accessd >>>

_______________________________________________
dba-VB mailing list
dba-VB at databaseadvisors.com
http://databaseadvisors.com/mailman/listinfo/dba-vb
http://www.databaseadvisors.com




More information about the dba-VB mailing list