2

In my C# code, I have a source DataTable, and want to query it, storing the results to another DataTable.

I have A DataTable with stgId, fromdate, todate, colorCode, something1, something2 as columns. After querying with the where condition I need to remove something1 and something2 columns and to get the result in another DataTable.

Equivalent SQL query would be as shown below

SELECT 
    stgId,
    fromdate,
    todate,
    colorCode 
FROM 
    tblScheduling 
WHERE 
    Mcode='123'

I want to get the result in another DataTable.

EDIT: Update After Answering

It is possible to get the result as DataRow[] type using where condition like this.

DataRow[] results = table.Select("A = 'foo' AND B = 'bar' AND C = 'baz'");

However I wanted the result set as new DataTable.
Quote from accepted answer
"Read about LINQ and lambda expression, they will be very useful for you. You can read about them here and here"

Community
  • 1
  • 1
Subin Jacob
  • 4,692
  • 10
  • 37
  • 69

2 Answers2

5

You can't use CopyToDataTable method directly, instead See: How to: Implement CopyToDataTable Where the Generic Type T Is Not a DataRow. After setting up your classes as per the link you can later call the method CopyToDataTable like:

var newDataTable = (dt.AsEnumerable()
                     .Where(r=> r.Field<string>("Mcode" == "123")
                     .Select new 
                           {
                           stgId = r.Field<int>("stgId"),
                           fromdate = r.Field<DateTime>("fromdate"),
                           todate = r.Field<DateTime>("todate"),
                           colorCode = r.Field<int>("colorCode")
                           }).CopyToDataTable();

Remember to use the correct type in Field extension method.

The above requires following two classes to be setup in your code. *(its from the same MSDN link)

public static class CustomLINQtoDataSetMethods
{
    public static DataTable CopyToDataTable<T>(this IEnumerable<T> source)
    {
        return new ObjectShredder<T>().Shred(source, null, null);
    }

    public static DataTable CopyToDataTable<T>(this IEnumerable<T> source,
                                                DataTable table, LoadOption? options)
    {
        return new ObjectShredder<T>().Shred(source, table, options);
    }

}

public class ObjectShredder<T>
{
    private System.Reflection.FieldInfo[] _fi;
    private System.Reflection.PropertyInfo[] _pi;
    private System.Collections.Generic.Dictionary<string, int> _ordinalMap;
    private System.Type _type;

    // ObjectShredder constructor.
    public ObjectShredder()
    {
        _type = typeof(T);
        _fi = _type.GetFields();
        _pi = _type.GetProperties();
        _ordinalMap = new Dictionary<string, int>();
    }

    /// <summary>
    /// Loads a DataTable from a sequence of objects.
    /// </summary>
    /// <param name="source">The sequence of objects to load into the DataTable.</param>
    /// <param name="table">The input table. The schema of the table must match that 
    /// the type T.  If the table is null, a new table is created with a schema 
    /// created from the public properties and fields of the type T.</param>
    /// <param name="options">Specifies how values from the source sequence will be applied to 
    /// existing rows in the table.</param>
    /// <returns>A DataTable created from the source sequence.</returns>
    public DataTable Shred(IEnumerable<T> source, DataTable table, LoadOption? options)
    {
        // Load the table from the scalar sequence if T is a primitive type.
        if (typeof(T).IsPrimitive)
        {
            return ShredPrimitive(source, table, options);
        }

        // Create a new table if the input table is null.
        if (table == null)
        {
            table = new DataTable(typeof(T).Name);
        }

        // Initialize the ordinal map and extend the table schema based on type T.
        table = ExtendTable(table, typeof(T));

        // Enumerate the source sequence and load the object values into rows.
        table.BeginLoadData();
        using (IEnumerator<T> e = source.GetEnumerator())
        {
            while (e.MoveNext())
            {
                if (options != null)
                {
                    table.LoadDataRow(ShredObject(table, e.Current), (LoadOption)options);
                }
                else
                {
                    table.LoadDataRow(ShredObject(table, e.Current), true);
                }
            }
        }
        table.EndLoadData();

        // Return the table.
        return table;
    }

    public DataTable ShredPrimitive(IEnumerable<T> source, DataTable table, LoadOption? options)
    {
        // Create a new table if the input table is null.
        if (table == null)
        {
            table = new DataTable(typeof(T).Name);
        }

        if (!table.Columns.Contains("Value"))
        {
            table.Columns.Add("Value", typeof(T));
        }

        // Enumerate the source sequence and load the scalar values into rows.
        table.BeginLoadData();
        using (IEnumerator<T> e = source.GetEnumerator())
        {
            Object[] values = new object[table.Columns.Count];
            while (e.MoveNext())
            {
                values[table.Columns["Value"].Ordinal] = e.Current;

                if (options != null)
                {
                    table.LoadDataRow(values, (LoadOption)options);
                }
                else
                {
                    table.LoadDataRow(values, true);
                }
            }
        }
        table.EndLoadData();

        // Return the table.
        return table;
    }

    public object[] ShredObject(DataTable table, T instance)
    {

        FieldInfo[] fi = _fi;
        PropertyInfo[] pi = _pi;

        if (instance.GetType() != typeof(T))
        {
            // If the instance is derived from T, extend the table schema
            // and get the properties and fields.
            ExtendTable(table, instance.GetType());
            fi = instance.GetType().GetFields();
            pi = instance.GetType().GetProperties();
        }

        // Add the property and field values of the instance to an array.
        Object[] values = new object[table.Columns.Count];
        foreach (FieldInfo f in fi)
        {
            values[_ordinalMap[f.Name]] = f.GetValue(instance);
        }

        foreach (PropertyInfo p in pi)
        {
            values[_ordinalMap[p.Name]] = p.GetValue(instance, null);
        }

        // Return the property and field values of the instance.
        return values;
    }

    public DataTable ExtendTable(DataTable table, Type type)
    {
        // Extend the table schema if the input table was null or if the value 
        // in the sequence is derived from type T.            
        foreach (FieldInfo f in type.GetFields())
        {
            if (!_ordinalMap.ContainsKey(f.Name))
            {
                // Add the field as a column in the table if it doesn't exist
                // already.
                DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name]
                    : table.Columns.Add(f.Name, f.FieldType);

                // Add the field to the ordinal map.
                _ordinalMap.Add(f.Name, dc.Ordinal);
            }
        }
        foreach (PropertyInfo p in type.GetProperties())
        {
            if (!_ordinalMap.ContainsKey(p.Name))
            {
                // Add the property as a column in the table if it doesn't exist
                // already.
                DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name]
                    : table.Columns.Add(p.Name, p.PropertyType);

                // Add the property to the ordinal map.
                _ordinalMap.Add(p.Name, dc.Ordinal);
            }
        }

        // Return the table.
        return table;
    }
}
Habib
  • 219,104
  • 29
  • 407
  • 436
  • 1
    @SonerGönül, I could have asked the OP to read about LINQ to DataSet and CopyToDataTable method, but then it would be an incomplete answer, IMO – Habib Mar 25 '13 at 07:32
  • Yeah, probably that's the reason of upvotes. Some people don't even care about their questions' quality.. They are not aware of they can get better answer when they ask better questions.. – Soner Gönül Mar 25 '13 at 07:34
  • @SubinJacob http://meta.stackexchange.com/questions/146513/what-does-op-mean **The characters "OP" stand for "Original Poster", the person originally asking the question.** – Soner Gönül Mar 25 '13 at 07:50
  • @SonerGönül My English is very bad I think. I always try to make questions better. Thats why I requested an edit for the question. – Subin Jacob Mar 25 '13 at 07:55
  • Can you explain me why `=>` its there. I'm not at all familiar with LINQ and lamda expressions and I'm a beginner too – Subin Jacob Mar 25 '13 at 07:56
  • @SubinJacob My english isn't perfect too. But you should always try your best. Please read [FAQ] and [ask] a couple of times.. – Soner Gönül Mar 25 '13 at 07:58
  • @SubinJacob, you should read about LINQ and lambda expression, they will be very useful for you. You can read about them [here](http://msdn.microsoft.com/en-us/library/bb397687.aspx) and [here](http://www.codeproject.com/Articles/33769/Basics-of-LINQ-Lamda-Expressions) – Habib Mar 25 '13 at 08:00
2
foreach (DataRow dr in dataTable1.Rows) {
    if (dr["Mcode"].ToString()=="123")
        dataTable2.Rows.Add(dr.ItemArray);
}

The above example assumes that dataTable1 and dataTable2 have the same number, type and order of columns.

Edit 1

You can use clone method to copy structure of existing datatable into another.

http://msdn.microsoft.com/en-IN/library/system.data.datatable.clone.aspx

Suppose you have a datatable dt1 So you can create a clone as follows

  DataTable dt2  = dt1.Clone();  

and use the above loop as follows

foreach (DataRow dr in dt1.Rows) {
    if (dr["Mcode"].ToString()=="123")
        dt2.Rows.Add(dr.ItemArray);
}
शेखर
  • 17,412
  • 13
  • 61
  • 117