在一个DataTable或数据集将其再利用LINQ的结果 [英] Reuse Linq result by adding it in a datatable or dataset

查看:472
本文介绍了在一个DataTable或数据集将其再利用LINQ的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

*的强大的文本的*感谢Tim谁给我提供的code低于本其他职位:<一href=\"http://stackoverflow.com/questions/13929780/join-merge-two-excel-files-in-asp-net-and-display-them-in-gridview\">Join/merge两人在asp.net Excel文件,并在GridView控件显示出来。

我在这个新职位的问题是:
我怎么可以重复使用或LINQ结果添加到数据集或datatabe这样我就可以查询新表,而不是两个单独的表? join关键字给了我加入这两个表的可能性。现在,我想用这个表要在其上运行其他查询。

我希望我的问题是有道理的。如果您需要更多的信息,请让我知道。

 的DataSet DS =新的DataSet(股票);
使用(VAR的DbConnection =新的OleDbConnection(CONNSTRING))
使用(VAR的DbCommand =新的OleDbCommand(SELECT * FROM [工作表Sheet1 $]的DbConnection))
使用(VAR DA =新OleDbDataAdapter的(的DbCommand))
{
    da.Fill(DSHWTypes);
}使用(VAR的DbConnection =新的OleDbConnection(stockConn))
使用(VAR的DbCommand =新的OleDbCommand(SELECT * FROM [Stock_voorlopig $]的DbConnection))
使用(VAR DA =新OleDbDataAdapter的(的DbCommand))
{
    da.Fill(DS,股票);
}VAR在ds.Tables [HWTypes] =加盟从舍入类型。AsEnumerable()
             在ds.Tables [股票]加入rStock。AsEnumerable()
             在rType.Field&LT;串GT(产品ID)等于rStock.Field&LT;串GT(型号封装)
             新选择
             {
                 的ProductID = rType.Field&LT;串GT(产品ID)
                 //添加您需要这里的其他列
             };
GridView1.DataSource =加入;
GridView1.DataBind();

编辑1:

我试图做这样的事情:

 私有静态数据表JoinDataTablesWithLinq()
{ //从上面的code休息
 返回joined.CopyToDataTable();
}

但我得到这个错误:

 类型'AnonymousType#1不能用作泛型类型或方法的类型参数'T' 'System.Data.DataTableExtensions.CopyToDataTable<T>(System.Collections.Generic.IEnumerable<T>)'.有一个从AnonymousType#1到的System.Data.DataRow'隐式引用转换。

任何帮助吗?


解决方案

  

我试图做这样的事情:


 私有静态数据表JoinDataTablesWithLinq()
{ //从上面的code休息
 返回joined.CopyToDataTable();
}

您不能创建一个数据表对飞。您选择匿名类型,是不是的IEnumerable&LT;&的DataRow GT; ,你需要使用的 CopyToDataTable 。所以,你要么必须使用自定义类,并填补了列表&LT; MyClass的&GT; 你需要坚持一切属性,或者您必须创建一个数据表所有必要的 DataColumns 匿名类型和填充。

您看,这不是那么容易。还有一个动态的方法虽然。但需要反思,因此它不是有效的。

在这里,我们去...(我的其他答案)

您可以创建自己的 CopyToDataTable 这需要任何形式的IEnumerable的(不仅的DataRow ),并返回一个新的数据表

下面是实现(与 MSDN )

 公共类ObjectShredder&LT; T&GT; {
    私人System.Reflection.FieldInfo [] _​​fi;
    私人System.Reflection.PropertyInfo [] _​​pi;
    私人System.Collections.Generic.Dictionary&LT;字符串,整数&GT; _ordinalMap;
    私人System.Type的_type;    // ObjectShredder构造函数。
    公共ObjectShredder(){
        _type = typeof运算(T);
        _fi = _type.GetFields();
        _pi = _type.GetProperties();
        _ordinalMap =新词典&LT;字符串,整数&GT;();
    }    ///&LT;总结&gt;
    ///从加载的对象序列的DataTable。
    ///&LT; /总结&gt;
    ///&LT; PARAM NAME =源&GT;对象的序列加载到数据表&LT; /参数&GT;
    ///&LT; PARAM NAME =表&gt;在输入表。表中的模式必须匹配
    ///类型T.如果表是空,一个新表与一个模式中创建
    ///公众性质和类型的字段T.&LT创建的; /参数&GT;
    ///&所述; PARAM NAME =选项&GT;指定如何从源序列值将被应用到
    表中的///现有行&LT; /参数&GT;
    ///&LT;收益方式&gt;从源序列中创建的DataTable&LT; /回报&GT;
    公开数据表撕碎(IEnumerable的&LT; T&GT;源数据表的表,LoadOption选择?){
        //从标顺序装载表如果T是一个基本类型。
        如果(typeof运算(T).IsPrimitive){
            返回ShredPrimitive(源,表,选项);
        }        //创建一个新表,如果输入表为空。
        如果(表== NULL){
            表=新的DataTable(typeof运算(T).Name点);
        }        //初始化序图和扩展表模式基于类型T.
        表= ExtendTable(表中的typeof(T));        //枚举源序列和对象的值加载到行。
        table.BeginLoadData();
        使用(IEnumerator的&LT; T&GT; E = source.GetEnumerator()){
            而(e.MoveNext()){
                如果(选项!= NULL){
                    table.LoadDataRow(ShredObject(表,e.Current),(LoadOption)选项);
                }其他{
                    table.LoadDataRow(ShredObject(表,e.Current),TRUE);
                }
            }
        }
        table.EndLoadData();        //返回表。
        返回表;
    }    公开数据表ShredPrimitive(IEnumerable的&LT; T&GT;源数据表的表,LoadOption选择?){
        //创建一个新表,如果输入表为空。
        如果(表== NULL){
            表=新的DataTable(typeof运算(T).Name点);
        }        如果(!table.Columns.Contains(值)){
            table.Columns.Add(值的typeof(T));
        }        //枚举源序列和标值装入行。
        table.BeginLoadData();
        使用(IEnumerator的&LT; T&GT; E = source.GetEnumerator()){
            [对象]值=新对象[table.Columns.Count]
            而(e.MoveNext()){
                值[table.Columns [价值]序号] = e.Current;                如果(选项!= NULL){
                    table.LoadDataRow(值,(LoadOption)选项);
                }其他{
                    table.LoadDataRow(值true);
                }
            }
        }
        table.EndLoadData();        //返回表。
        返回表;
    }    公用对象[] ShredObject(DataTable的表,T实例){        字段信息[] F1 = _fi;
        的PropertyInfo [] =圆周率_pi;        如果(instance.GetType()!= typeof运算(T)){
            //如果实例在T衍生,扩展表模式
            //并获得属性和字段。
            ExtendTable(表,instance.GetType());
            F1 = instance.GetType()GetFields()。
            PI = instance.GetType()的GetProperties()。
        }        //实例的属性和字段值添加到一个数组。
        [对象]值=新对象[table.Columns.Count]
        的foreach(字段信息f由于FI){
            值[_ordinalMap [f.Name] = f.GetValue(实例);
        }        的foreach(的PropertyInfo中的p PI){
            值[_ordinalMap [p.Name] = p.GetValue(例如,NULL);
        }        //返回实例的属性和字段值。
        返回值;
    }    公开数据表ExtendTable(数据表的表,类型类型){
        //扩展表模式,如果输入表为空或者如果该值
        序列中//从T类型派生
        的foreach(字段信息f由于type.GetFields()){
            如果(!_ordinalMap.ContainsKey(f.Name)){
                //添加字段作为列的表,如果它不存在,
                // 已经。
                DataColumn的DC = table.Columns.Contains(f.Name)? table.Columns [f.Name]
                    :table.Columns.Add(f.Name,f.FieldType);                //将字段添加到地图序。
                _ordinalMap.Add(f.Name,dc.Ordinal);
            }
        }
        的foreach(在type.GetProperties的PropertyInfoρ()){
            如果(!_ordinalMap.ContainsKey(p.Name)){
                //添加属性作为列在表中,如果它不存在,
                // 已经。
                DataColumn的DC = table.Columns.Contains(p.Name)? table.Columns [p.Name]
                    :table.Columns.Add(p.Name,p.PropertyType);                //将属性添加到地图序。
                _ordinalMap.Add(p.Name,dc.Ordinal);
            }
        }        //返回表。
        返回表;
    }
}

现在你可以添加这些扩展:

 公共静态类CustomLINQtoDataSetMethods {
    公共静态数据表CopyToDataTable&LT; T&GT;(这个IEnumerable的&LT; T&GT;源){
        返回新ObjectShredder&LT; T&GT;()撕碎(源,NULL,NULL);
    }    公共静态数据表CopyToDataTable&LT; T&GT;(这个IEnumerable的&LT; T&GT;源,
                                                DataTable的表,LoadOption?选项​​){
        返回新ObjectShredder&LT; T&GT;()撕碎(源,表选项)。
    }
}

瞧!现在 CopyToDataTable 与任何一种的IEnumerable&LT工程; T&GT; :)

*strong text*Thanks to Tim who provided me the code below in this other post: Join/merge two excel files in asp.net and display them in gridview.

My question in this new post is: How can I reuse or add linq result to a dataset or datatabe so that I can query the new table and not the two separate tables? The join keyword gave me the possibility to join the two tables. Now I would like to use this joined table to run other queries on it.

I hope my question makes sense. If you need more info, please let me know.

DataSet ds = new DataSet("Stock");
using (var dbConnection = new OleDbConnection(connString))
using (var dbCommand = new OleDbCommand("SELECT * FROM [Sheet1$]", dbConnection))
using (var da = new OleDbDataAdapter(dbCommand))
{
    da.Fill(ds, "HWTypes");
}

using (var dbConnection = new OleDbConnection(stockConn))
using (var dbCommand = new OleDbCommand("SELECT * FROM [Stock_voorlopig$]", dbConnection))
using (var da = new OleDbDataAdapter(dbCommand))
{
    da.Fill(ds, "Stock");
}

var joined = from rType in ds.Tables["HWTypes"].AsEnumerable()
             join rStock in ds.Tables["Stock"].AsEnumerable()
             on rType.Field<string>("ProductID") equals rStock.Field<string>("Partno")
             select new
             {
                 ProductID = rType.Field<string>("ProductID")
                 // add the other columns you need here
             };


GridView1.DataSource = joined;
GridView1.DataBind();

Edit 1:

I am trying to do something like this:

private static DataTable JoinDataTablesWithLinq()
{

 //rest of the code from above
 return joined.CopyToDataTable();
}

But I am getting this error:

The type 'AnonymousType#1' cannot be used as type parameter 'T' in the generic type or method 'System.Data.DataTableExtensions.CopyToDataTable<T>(System.Collections.Generic.IEnumerable<T>)'. There is no implicit reference conversion from 'AnonymousType#1' to 'System.Data.DataRow'.

Any help?

解决方案

I am trying to do something like this:

private static DataTable JoinDataTablesWithLinq()
{

 //rest of the code from above
 return joined.CopyToDataTable();
}

You cannot create a DataTable "on the fly". You have selected an anonymous type which is not a IEnumerable<DataRow> which you need to use CopyToDataTable. So you either have to use a custom class and fill a List<MyClass> with all properties you need to persist it or you have to create a DataTable with all necessary DataColumns of the anonymous type and fill that.

You see that it's not that easy. There's one dynamic approach though. But that requires reflection, therefore it's not efficient at all.

Here we go... (extract of my other answer)

You could build your own CopyToDataTable that takes any kind of IEnumerable(not only DataRow)and returns a new DataTable:

Here is the implementation (with help of MSDN):

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;
    }
}

Now you can add these extensions:

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);
    }  
}

Voilà! Now CopyToDataTable works with any kind of IEnumerable<T> :)

这篇关于在一个DataTable或数据集将其再利用LINQ的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆