Tuesday, February 4, 2014

Writing Data in Excel File into a Database using a DataSet and SqlBulkCopy

In this post let’s see how we can write data in a excel file into a database using a DataSet and SqlBulkCopy.

The concept here is fairly simple. First I am going to load data in the excel file into a DataSet and then for each tables in the DataSet, I am going to use SqlBulkCopy to push the data into the database. In my case, it will be a single table.

For demonstration purpose I have the following excel file, which has only one sheet which is  named as “MySheet”.

Excel
Excel Sheet
Now let’s see the whole process in action. I’m creating a new console application. I have the following method to get excel data into a table in DataSet.
public static DataSet ReadToDataSet(string filePath, string tableName)
{
    DataSet ds = new DataSet();
    OleDbCommand cmd = new OleDbCommand();
    OleDbDataAdapter adapter = new OleDbDataAdapter();
    OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';");
 
    try
    {
        conn.Open();
        cmd.Connection = conn;
        cmd.CommandType = CommandType.Text;
 
        // to select all the columns
        //cmd.CommandText = "SELECT * FROM [MySheet$]";
 
        // I am only selecting some columns
        cmd.CommandText = "SELECT FirstName, LastName, Department FROM [MySheet$]";
 
        adapter = new OleDbDataAdapter(cmd);
        adapter.Fill(ds, tableName);
        return ds;
    }
    catch (Exception ex)
    { 

    }
    finally
    {
        conn.Close();
    }
    return null;
}
Here when creating the OleDbConnection, in the query string along with the excel file path, I have mentioned some properties.
  • "HDR=Yes;" indicates that the first row contains columnnames. If "HDR=No;", it indicates the opposite.
  • MEX=1 is a safer way to retrieve data for mixed data columns. (You can read more on excel connection strings on http://www.connectionstrings.com/excel/).
Once I do that, now I have to push the data in my DataSet into the database. Before doing that here I have following two helper methods.

Following method will check if a table already exists with the given name in the database.
private static bool CheckWhetherTableExists(SqlConnection conn, string tableName)
{
    bool isExist = false;
    SqlCommand cmd;
    try
    {
        conn.Open();
        cmd = new SqlCommand("SELECT * FROM sysobjects where name = '" + tableName + "'", conn);
        isExist = cmd.ExecuteScalar() == null ? false : true;
        return isExist;
    }
    catch (Exception ex)
    {
 
    }
    finally
    {
        conn.Close();
    }
    return true;
}
If the table doesn't exist, following method will create a table with all the column names as in provided DataTable. Please note, here for all columns I am using “varchar(MAX)” as the column type.
private static void CreateTableInDatabase(SqlConnection conn, DataTable dt)
{
    bool isExist = false;
    SqlCommand cmd;
    try
    {
        conn.Open();
        foreach (DataColumn dc in dt.Columns)
        {
            if (!isExist)
            {
                cmd = new SqlCommand("CREATE TABLE " + dt.TableName + " (" + dc.ColumnName + " varchar(MAX))", conn);
                cmd.ExecuteNonQuery();
                isExist = true;
            }
            else
            {
                cmd = new SqlCommand("ALTER TABLE " + dt.TableName + " ADD " + dc.ColumnName + " varchar(MAX)", conn);
                cmd.ExecuteNonQuery();
            }
        }
    }
    catch (Exception ex)
    {
 
    }
    finally
    {
        conn.Close();
    }
}
Once I have the DataSet and the table created in database, all I have to do now is push the data in DataSet into the database.
public static void PushDataSetToDatabase(SqlConnection conn, DataSet ds)
{
   try
   {
       foreach (DataTable dt in ds.Tables)
       {
           if (!CheckWhetherTableExists(conn, dt.TableName))
           {
               CreateTableInDatabase(conn, dt);
           }
 
           conn.Open();
           using (SqlBulkCopy bulkcopy = new SqlBulkCopy(conn))
           {
               bulkcopy.DestinationTableName = dt.TableName;
               bulkcopy.WriteToServer(dt);
           }
       }
   }
   catch (Exception ex)
   {
       
   }
   finally
   {
       conn.Close();
   }
}
Finally from the Main method, I am initiating the process.
static void Main(string[] args)
{
    string filePath = @"D:\SampleExcelFile.xlsx";
    DataSet ds = ReadToDataSet(filePath, "MyTable");
 
    SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=MyTestDB;Integrated Security=True");
    PushDataSetToDatabase(conn, ds);
}
Once the program completed, I can see the data in my database table.

Picture
Table in the Database

So that's it. I have uploaded the sample into my SkyDrive.


Happy Coding.

Regards,
Jaliya

Sunday, February 2, 2014

MapIt Privacy Policy

MapIt Privacy Policy

The "MapIt" privacy policy ensures the information collected from you via "MapIt" is totally secured. Your privacy is extremely important to me. As a result, I have implemented this Privacy Policy to ensure your information is safe.

Personal Data

This application does not share personal information with third parties nor does it store any information about you. (e.g. your name, address, telephone number or e-mail address). If you have any questions feel free to contact me directly at following email addresses.

     jaliya.udagedara@hotmail.com
     jaliya.udagedara@gmail.com

Thank You.

Sincerely,
Jaliya Udagedara

Wednesday, January 29, 2014

ERROR [IM014] [Microsoft][ODBC Driver Manager] The specified DSN contains an architecture mismatch between the Driver and Application

I was trying to pull data from AS400s’ DB2 database from a SQL Server Analysis Services project. Once I run my SSAS project, I was getting this error “ERROR [IM014] [Microsoft][ODBC Driver Manager] The specified DSN contains an architecture mismatch between the Driver and Application”. But to my surprise from my ADO.NET Source, when I previewed my query I was getting data as expected.

My DSN was 32-bit and I was using 32-bit BIDS in my 64-bit computer.

Picture1
Project Properties Window
Since data is retrieved when I click on Preview inside my ADO.NET Source, I was sure there is nothing wrong in the DSN. So there should be something wrong with the project. Went to project Properties and under “Debugging” changed “Run64BitRuntime” to false.

No more errors and it was perfectly working.

Happy Coding.

Regards,
Jaliya

Tuesday, January 21, 2014

Visual C# Technical Guru - December 2013

Became the Visual C# Technical Guru for the last month of the year 2013. There was not much of a competition this time, only two contestants including myself.

The TechNet Guru Awards celebrate the technical articles on Microsoft TechNet.

Post in WikiNinjas Official Blog,
Picture
Visual C# Technical Guru - December 2013
Happy Coding.

Regards,
Jaliya

Wednesday, January 15, 2014

Lock Statement in C#

Lock statement can be really useful when you are writing multi threaded applications. Basically what lock statement does is, it monitors and prevents some particular blocks of code from being accessed simultaneously by multiple threads.

It's always good to go by an example. First I am creating a very simple multi threaded application without any lock statements. I am having a class there named “MyClass” which will have a single method.
public class MyClass
{
    public void MyMethodWithoutLock()
    {
        Thread.Sleep(5000);
        Console.WriteLine("Without Lock " + DateTime.Now);
    }
}
Inside the above method, let’s assume that I am doing some time consuming work and then I am printing out a message with the current time.

Inside the Main method, I am going to create a object of “MyClass” and I am going to call the “MyMethodWithoutLock” from some different threads.
class Program
{
    static void Main(string[] args)
    {
        MyClass oMyClass = new MyClass();
        List<Thread> threads = new List<Thread>();
 
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(oMyClass.MyMethodWithoutLock);
            threads.Add(t);
        }
 
        foreach (Thread t in threads)
        {
            t.Start();
        }
 
        Console.WriteLine(DateTime.Now);
    }
}
Here there is nothing complex, just some very simple multi threading. I have created a object of "MyClass" and created a variable to hold list of threads. Then I have added 5 threads to threads list which will call the “MyMethodWithoutLock” of my one and only object “oMyClass”. Finally I am starting all the threads at once and printing out the current time. Please note that in my Main method, I have created only a single object of “MyClass”

So the output will be as follows.
Pic1
Without Lock
As you can see after starting the treads at 11:35:01, all the threads has completed calling “MyMethodWithoutLock” simultaneously at 11:35:06. So the point here is all threads have been calling “MyMethodWithoutLock” at the same time which is a prefect concurrency.

Now let’s say, I have a scenario where I have two methods. One method should be called simultaneously and the other should not be called simultaneously. For this I can use the lock statement and let’s see how.

Hers is my modified class.
public class MyClass
{
    private Object thisLock = new Object();
 
    public void MyMethodWithoutLock()
    {
        Thread.Sleep(5000);
        Console.WriteLine("Without Lock " + DateTime.Now);
    }
 
    public void MyMethodWithLock()
    {
        lock (thisLock)
        {
            Thread.Sleep(5000);
            Console.WriteLine("With Lock " + DateTime.Now);
        }
    }
}
Inside Main, I will have some threads as previous, the only difference is, my threads will be calling both these two methods as below.
class Program
{
    static void Main(string[] args)
    {
        MyClass oMyClass = new MyClass();
        List<Thread> threads = new List<Thread>();
 
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(new ThreadStart(() =>
            {
                oMyClass.MyMethodWithoutLock();
                oMyClass.MyMethodWithLock();
            }));
            threads.Add(t);
        }
 
        foreach (Thread t in threads)
        {
            t.Start();
        }
 
        Console.WriteLine(DateTime.Now);
    }
}
Now the output will be as follows.
Pic2
With Lock
If you can see here, my set of threads has called “MyMethodWithoutLock” method simultaneously. But “MyMethodWithLock” method has been called by only one single thread at a time. After one thread completed executing “MyMethodWithLock” method, then another thread came in and has accessed “MyMethodWithLock”.

Now if you have read the above well, I have mentioned I have created only a single object of “MyClass”. Let’s modify the above code where I am creating several objects of “MyClass” and each thread will be accessing separate objects’ methods.
class Program
{
    static void Main(string[] args)
    {
        List<Thread> threads = new List<Thread>();
 
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(new ThreadStart(() =>
            {
                MyClass oMyClass = new MyClass();
                oMyClass.MyMethodWithoutLock();
                oMyClass.MyMethodWithLock();
            }));
            threads.Add(t);
        }
 
        foreach (Thread t in threads)
        {
            t.Start();
        }
 
        Console.WriteLine(DateTime.Now);
    }
}
So the output will be as follows.
Pic3
With Lock Different Objects
Now here what has happened is both the methods has been called simultaneously back again. This explains the very basic concept of the lock statement. That is lock will only be blocking some code from accessing multiple threads only when the code belongs to same object. If the threads are accessing same method of different objects and still you want to block some code from multi thread access, if you use lock statement, basically it’s not going to help you.

For more information,
   lock Statement (C# Reference)
   Thread Synchronization

I am uploading the sample to my SkyDrive, do enjoy.


So hope this helps. Appreciate your all feedback.

Happy Coding.

Regards,
Jaliya

Tuesday, January 14, 2014

Microsoft Visual Studio Has Tweeted One Of My Wikis’

Microsoft Visual Studio has tweeted one of my wikis’. I was really surprised and felt so happy to see this tweet.
Untitled1
Microsoft Visual Studio has tweeted one of my wikis
Here is my wiki which was tweeted by @VisualStudio
   Visual C#: Thread.Sleep vs. Task.Delay

Happy Coding.

Regards,
Jaliya

Tuesday, January 7, 2014

Changing Entity Framework default connection factory from LocalDb to Microsoft SQL Server

When you create a project let’s say a Console Application and add Entity Framework, as you know EF will modify the existing app.config file by adding some EF relevant configurations (If you are creating a Web Application, EF will modify the web.config file.).

Now let’s say you are using Code First and adding some data. But you might be wondering where you have mentioned the connection string etc.. EF maintains these configurations in the configuration file and after EF5, it uses LocalDb as the defaultConnectionFactory. Previously it was using SQL Express.

Something extra, if you are wondering why use LocalDb, it’s because of this. Since SQL Express is the free version of Microsoft SQL Server and most developers that target SQL Server, tend to use SQL Express in their development machines. But with LocalDb they no longer have to install and manage a full instance of SQL Express, as the same T-SQL language, programming surface and client-side providers are provided with LocalDb.

So getting back to the topic, as I mentioned before, the app/web.config will be holding this defaultConnectionFactory setting for EF.
<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
</entityFramework>
Here you can see the defaultConnectionFactory is set to LocalDbConnectionFactory. Under the parameters, you can find the LocalDb version. For example, v11.0 represents SQL Server 2012.

Now let’s say you want to change the defaultConnectionFactory to a SQL Server instance. For that you will have to change the configuration as follows.
<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="Data Source=.;Integrated Security=True" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
</entityFramework>
From now onwards, Entity Framework will use SQL Server as the defaultConnectionFactory for that particular application.

Something important to add here, with the release of EF6, it has introduced a new feature which is Code-Based Configuration. Using Code-Based Configuration you can mention the defaultConnectionFactory too. But the config file takes precedence over Code-Based configuration. In other words, if a configuration option is set in both code and in the config file, then the setting in the config file is used.

Happy Coding.

Regards,
Jaliya

Saturday, January 4, 2014

Session : Lap Around Entity Framework at Sri Lanka .NET Forum

Yesterday conducted a session at Sri Lanka .NET Forum.



I have uploaded the slide deck and demo projects to my SkyDrive. Do check it out.



Happy Coding.

Regards,
Jaliya

Thursday, January 2, 2014

Received Microsoft MVP Award for Visual C#

This is going to be my first post in this new year 2014.

Received the Microsoft Most Valuable Professional (MVP) Award for Visual C# and this is my first time. Feeling so great and I definitely will be keeping my contributions towards Visual C# technical community in every possible way.
MVPLogo
Microsoft Most Valuable Professional (MVP)
Thanks a lot Fiqri Ismail, Wellington Perera and Joy Rathnayake for everything. And Thank you much Microsoft. Really Means a lot.

Happy Coding.

Regards,
Jaliya