Thursday, January 12, 2012

How to create a datatable programmatically

Hi, Today I want to discuss  about how to create a datatable programmatically.
Actually it's very easy.
We need complete next few steps:

  1. Declare DataTable
  2. Declare Columns
  3. Add columns to DataTable
  4. Fill Rows of DataTable with data if you need.
Yes, that's all.
OK, Let me show some sort of example, How I did it:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using System;
using System.Data;

namespace HowToDataTableProgr
{
    class Program
    {
        class CompanyInfo
        {
            public CompanyInfo(string CompanyName, string CompanyAddress, double budget)
            {
                this.CompanyAddress = CompanyAddress;
                this.CompanyName = CompanyName;
                this.budget = budget;
            }
            public string CompanyName { get; set; }
            public string CompanyAddress { get; set; }

            private double budget;


            public string GetBudget()
            {
                return this.budget.ToString("C0");
            }



        }

        static void Main(string[] args)
        {

            var dataTable = new DataTable();

            var columnId = new DataColumn("Id", typeof(int));
            columnId.AutoIncrement = true;
            var columnCity = new DataColumn("City", typeof(string));
            var columnCompany = new DataColumn("compInfo", typeof(CompanyInfo));
            dataTable.Columns.AddRange(new DataColumn[] { columnId, columnCity, columnCompany });

            //add values into  rows
            dataTable.Rows.Add(null, "Washington", new CompanyInfo("Bradly co", "someStreet 12", 10000000.0));
            dataTable.Rows.Add(null, "New York", new CompanyInfo("Pooply ltd", "lane stree 45 12", 4000000.0));
            dataTable.Rows.Add(null, "Cupertino", new CompanyInfo("NewGoggle", "W Fremon AVe 2", 70000000.0));
            dataTable.Rows.Add(null, "Sidney", null);

            //Show names of Columns
            Console.WriteLine("DataTable has {0} DataColumns named:",
                dataTable.Columns.Count);
            foreach (DataColumn currentColumn in dataTable.Columns)
                Console.WriteLine("\t{0}", currentColumn.ColumnName);
            
            //show  count of rows
            Console.WriteLine("DataTable has {0} rows: ",
                dataTable.Rows.Count);
            Console.WriteLine();

            //show all data from all rows
            foreach (DataRow dataRow in dataTable.Rows)
            {
                foreach (DataColumn dataColumn in dataTable.Columns)
                {
                    if (dataRow[dataColumn] is CompanyInfo)
                    {
                        var currentCompany = dataRow[dataColumn] as CompanyInfo;
                        if (currentCompany != null)
                            Console.WriteLine(string.Format("CompanyAddress:{0}, CompanyName={1}, budget={2}", currentCompany.CompanyAddress, currentCompany.CompanyName, currentCompany.GetBudget()));                        
                    }
                    else
                        Console.WriteLine(dataRow[dataColumn].ToString());
                }
                Console.WriteLine();

            }
            Console.ReadKey();
        }
    }

}

Not sure, But I think  you have a few questions regarding source code.
Why so complex? you can ask me.
You see, right, If you need create  DataTable  and that's all, then it should looks like:

1
2
3
4
5
6
7
8
var dataTable = new DataTable();//declare DataTable

            var columnId = new DataColumn("Id", typeof(int));//declare column
            columnId.AutoIncrement = true;//set as columnId.AutoIncrement
            var columnCity = new DataColumn("City", typeof(string));//declare column
            var columnCompany = new DataColumn("compInfo", typeof(CompanyInfo));//declare column

            dataTable.Columns.AddRange(new DataColumn[] { columnId, columnCity, columnCompany });//add Range of columns to existed DataTable



Wednesday, January 11, 2012

How to convert List<string> into solid string

I few days ago I've stuck with  really trivial  things. I have to convert List to solid string with delimiter in my high-performance application. I've decided to write some test for this purpose.  

What I'll test:

  • Aggregate Linq extension method.
  • StringBuilder and loop class.
  • string.Concat - yeah, It's not my best code, especially  if I use Concat method in wrong way =)
  • String.Join static method.


Let's do that:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class Program
    {
        static void Main(string[] args)
        {
            //generate some data for our test
            var tstList = Enumerable.Range(1, 10000).Select(i => i.ToString()).ToList();
            string delimeter = ",";

            #region List<string> to solid string using Linq extension method
            Stopwatch sw = Stopwatch.StartNew();//start measure time
            string result1 = tstList.Aggregate((i, j) => i + delimeter + j);//run string cancatination using Linq extension
            sw.Stop(); //stop measuring

            Console.WriteLine("linq aggregate func took\t {0}", sw.Elapsed.ToString()); //show result on screen
            #endregion

            #region  List<string> to solid string using StringBuilder class            
            StringBuilder sb = new StringBuilder();
            bool isEmpty = true;
            sw = Stopwatch.StartNew();//start measure time
            for (int i = 0; i < tstList.Count(); i++)
            {//yeah some mess here, I know =)
                if (!isEmpty)
                    sb.Append(",");
                sb.Append(tstList[i]);
                isEmpty = false;
            }            
            sw.Stop(); //stop measuring
            Console.WriteLine("for loop and StringBuilder took\t {0}", sw.Elapsed.ToString());
            #endregion

            
            
            string result3 = string.Empty;
            isEmpty = true;
            sw = Stopwatch.StartNew();//start measure time
            for (int i = 0; i < tstList.Count(); i++)
            {
                if (!isEmpty)
                    result3 = string.Concat(result3, ",");

                result3 = string.Concat(result3, tstList[i]);
                isEmpty = false;
            }
            sw.Stop(); //stop measuring
            Console.WriteLine("string.Concat took\t\t {0}", sw.Elapsed.ToString());


            #region  List<string> to solid string using String.Join
            string result4 = string.Empty;
            sw = Stopwatch.StartNew();//start measure time
            result4 = String.Join(delimeter, tstList.ToArray());
            sw.Stop();
            Console.WriteLine("string.Join took\t\t {0}", sw.Elapsed.ToString());
            #endregion
            //Console.WriteLine(result3); //for test 
            Console.ReadKey();

        }
    }

As result I've got something like that:

I'm really disappointed with Linq Extension Aggregate method. It  takes forever to finish so simple thing.
What  about other methods?
StringBuilder. In every book you will see, that StringBuilder is best for frequently changing strings, because of string class is mutable. Mmmm... I don't know,  I think,  if you have any chance to use string.Concat, do it.
As you can see, string.Concat- is the super fast.
Yeah, I'm definitely will use string.Concat in my  application instead of Linq methods.
and What do you think?
Does Linq  good enough to use in  production environment?

Tuesday, January 10, 2012

Comparing Linq performance.

I heard some rumours in internet,  that  we have to avoid LINQ, because it's slow.  What can I do here? Right, I gonna write my own  test.
I decided to test following  scope of methods:

  • A simple foreach loop
  • A simple for loop
  • Using the ICollection.Contains method
  • The Any extension method using HashSet
  • The Any extension method ("LINQ")

Here is  source code of my app:
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
class Program
    {
        /// <summary>
        /// this method for testing performance only
        /// It runs Action method in the loop and uses Stopwatch to track time.
        /// </summary>
        /// <param name="funcList">list of delegates and  some  additional help strings</param>
        static void ProfileReport(Dictionary<string, Action> funcList)
        {
            foreach (var func in funcList)
            {
                Stopwatch sw = Stopwatch.StartNew();//start timer
                var f = func.Value;//get instance of current delegate
                f();//execute it
                sw.Stop();//stop time tracking
                Console.WriteLine(func.Key + '\t' + sw.Elapsed.ToString());//here is result
                GC.Collect();// removing unnecesary  data before next iteration
            }
            Console.WriteLine();
        }

        static void Main(string[] args)
        {
            var names = Enumerable.Range(1, 1000000).Select(i => i.ToString()).ToList();//generate some test values as sequence of numbers
            var namesHash = new HashSet<string>(names);
            string testName = "99999";
            for (int i = 0; i < 10; i++)
            {
                ProfileReport(new Dictionary<string, Action>() 
            {
                { "Foreach Loop\t", () => Search(names, testName, ContainsForeachLoop) },    
                { "For Loop\t", () => ContainsForLoop(names,testName) },    
                { "Enumerable.Any\t", () => Search(names, testName, ContainsAny) },                
                { "HashSet\t\t", () => Search(namesHash, testName, ContainsCollection) },
                { "ICollection.Contains", () => Search(names, testName, ContainsCollection) }
            });


            }
            Console.ReadLine();
        }
        static bool ContainsAny(ICollection<string> names, string name)
        {
            return names.Any(s => s == name);
        }

        static bool ContainsCollection(ICollection<string> names, string name)
        {
            return names.Contains(name);
        }

        static bool ContainsForeachLoop(ICollection<string> names, string name)
        {
            foreach (var currentName in names)
            {
                if (currentName == name)
                    return true;
            }
            return false;
        }

        static bool ContainsForLoop(List<string> names, string name)
        {
            for (int i=0; i<names.Count(); i++)
            {
                if (names[i] == name)
                    return true;
            }
            return false;
        }


        static bool Search(ICollection<string> names, string name,
        Func<ICollection<string>, string, bool> containsFunc)
        {
            return (containsFunc(names, name) ? true : false);
        }
    }

As result, I've got:

I'm little bit surprized here. I thought, that "For" loop will be faster then  foreach because  in for loop we don't need copy current value on every iteration from entiredata list. Yes, It looks like miracle, I can't  explaine it right now, I have to check it in msdn. But any way, lets back to LINQ, this is  our main point of all these  measurements.

So, as you can see, LINQ is really slower then foreach loop, HashSet and ICollection.Contains.
It should be avoided if it is not fast enoughSlow and not fast enough are not at all the same thing!
Slow is irrelevant to our customers.
I found some discussions  related to this topic, for example some guys things like:

"Performance optimization is expensive. Writing code so that it can be read and maintained by others is expensive. Those goals are frequently in opposition to each other, so in order to spend your customer's money responsibly you've got to ensure that you're only spending valuable time and effort doing performance optimizations on things that are not fast enough. "


But I do not agree, I believe, we have to write good for reading but also fast code.
So if I will have posibility to avoid LINQ, will do. =)

Thursday, January 5, 2012

A few words about C# extension

A few days ago I was digging MDN C# field for something interesting for me.  It was several articles about C# extension methods. It’s quite useful things.
The basic idea is that the set of methods available on an instance of a particular type is open to extension. As result, we can add new methods to existing types.  I thing most of us  already impacted with  some issues such as requirements to extend third party  classes, sealed classes and so on. In such cases, most general way here is create “helper” class or methods and use it everywhere. Sure, it can be.
C# has better solution.
Imagine we are wants to get all Mondays start from selected date.
Piece of cake, check result:





1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DateTimeExtensions;



namespace DateTimeExtensions{
 public static class DateHelper
    {
        public static IEnumerable&lt;DateTime&gt; GetMondays(this DateTime startDate)
        {
            DateTime endDate = new DateTime(startDate.Year, 12, 31);

            while (startDate.DayOfWeek != DayOfWeek.Monday)
                startDate = startDate.AddDays(1);

            while (startDate &lt; endDate)
            {
                yield return startDate;
                startDate = startDate.AddDays(7);
            }
        }
    }
}
namespace UsingExtensions
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime startDate = new DateTime(1983, 7, 23); //
            foreach (DateTime monday in startDate.GetMondays())
                Console.WriteLine(monday.ToString());
               
            Console.ReadKey();
        }      
    }

}





At the end of the end I would like to provide several rules:
couple of rules to consider when deciding on whether or not to use extension methods:

·         Extension methods cannot be used to override existing methods

·         An extension method with the same name and signature as an instance method will not be called

·         The concept of extension methods cannot be applied to fields, properties or events

·         Do not overuse extension methods; it can be a bad thing!

Wednesday, January 4, 2012

I'm back

Yes. I decided to back. I would say Hello world, or it will be better to say hello world again.
So, what I'm going to write about?
I'll continue highlighting new feature of .Net, most memorable and exciting things that I like in C# and Oracle.
So, please, feel free check my blog from time to time. Comment my articles; I'll be pleasure to discuss with you.

Thanks,
Max