Linq 将实体模型转换为数据集-可以这样做吗?

Linq 将实体模型转换为数据集-可以这样做吗?,linq,datatable,dataset,entity,linq-to-dataset,Linq,Datatable,Dataset,Entity,Linq To Dataset,我在这里很沮丧。。。 对于.Net中的复杂问题,我通常可以在网络上的某个地方找到某种答案,但我无法找到这个答案。 我所处的场景是,我必须将LINQ to Entity查询的结果转换为数据集,这样数据就可以由现有业务逻辑处理,而我找不到一个解决方案 我尝试过一些基本的方法,比如EntityCommand生成读取器,但这一方法不起作用,因为DataTable.Load()执行了一个Exception(EntityCommand生成的读取器不支持GetSchemaTable() 我还尝试了更为友好的方

我在这里很沮丧。。。 对于.Net中的复杂问题,我通常可以在网络上的某个地方找到某种答案,但我无法找到这个答案。 我所处的场景是,我必须将LINQ to Entity查询的结果转换为数据集,这样数据就可以由现有业务逻辑处理,而我找不到一个解决方案

我尝试过一些基本的方法,比如EntityCommand生成读取器,但这一方法不起作用,因为DataTable.Load()执行了一个Exception(EntityCommand生成的读取器不支持GetSchemaTable()

我还尝试了更为友好的方法,比如实体到IDataReader(http://l2edatareaderadapter.codeplex.com/),但这一个抛出了异常,文档很少,而且自2008年以来从未被触及过

我发现的另一个方法是这里(http://blogs.msdn.com/b/alexj/archive/2007/11/27/hydrating-an-entitydatareader-into-a-datatable-part-1.aspx),但没有该守则的有效副本;只有片段

我发现很难相信,首先MS不会提供这种现成的向后兼容性项目,其次,它也不会由社区创建

如果有的话,我也愿意考虑商业解决方案


谢谢

这可能不是最好的解决方案,但是如果您的场景中只有一个或两个表需要添加到数据集中,为什么不直接手动构建它们呢

var result = db.YourTable; // get your Linq To Entities result.

DataSet ds = new DataSet();
DataTable tbl = new DataTable();
tbl.Columns.Add("col1", typeof(string));
tbl.Columns.Add("col2", typeof(int));

foreach (var r in result)
{
  var row = tbl.NewRow();
  row[0] = r.Col1;
  row[1] = r.Col2;

  tbl.Rows.Add(r);
}

ds.表格。添加(待定)


Col1和Col2来自Linq To Entity对象,您可以像这样创建所有需要的表并返回数据集。

您可以将结果转换为列表,并使用以下命令将列表转换为数据表

public DataTable ConvertToDataTable<T>(IList<T> data)
    {
        PropertyDescriptorCollection properties =
           TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        foreach (PropertyDescriptor prop in properties)
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        foreach (T item in data)
        {
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
            table.Rows.Add(row);
        }
        return table;

    }
公共数据表ConvertToDataTable(IList数据)
{
PropertyDescriptorCollection属性=
GetProperties(typeof(T));
DataTable=新的DataTable();
foreach(属性中的PropertyDescriptor属性)
table.Columns.Add(prop.Name,Nullable.GetUnderlyingType(prop.PropertyType)??prop.PropertyType);
foreach(数据中的T项)
{
DataRow行=table.NewRow();
foreach(属性中的PropertyDescriptor属性)
行[prop.Name]=prop.GetValue(项)??DBNull.Value;
table.Rows.Add(行);
}
返回表;
}

希望这有帮助


Preetam

这是一个灵活的代码,可以满足您的大部分需求:

public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
    {
        DataTable dtReturn = new DataTable();
        // column names
        PropertyInfo[] oProps = null;
        if (varlist == null) return dtReturn;
        foreach (T rec in varlist)
        {
            // Use reflection to get property names, to create table, Only first time, others will follow
            if (oProps == null)
            {
                oProps = ((Type)rec.GetType()).GetProperties();
                foreach (PropertyInfo pi in oProps)
                {
                    Type colType = pi.PropertyType;
                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                    {
                        colType = colType.GetGenericArguments()[0];
                    }

                    dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
                }
            }

            DataRow dr = dtReturn.NewRow();
            foreach (PropertyInfo pi in oProps)
            {
                dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
                (rec, null);
            }

            dtReturn.Rows.Add(dr);
        }

        return dtReturn;
    }
公共数据表LINQTODatable(IEnumerable varlist)
{
DataTable dtReturn=新DataTable();
//列名
PropertyInfo[]oProps=null;
if(varlist==null)返回dtReturn;
foreach(varlist中的T rec)
{
//使用反射来获取属性名,创建表,只有第一次,其他人会跟随
if(oProps==null)
{
oProps=((Type)rec.GetType()).GetProperties();
foreach(oProps中的属性信息pi)
{
类型colType=pi.PropertyType;
if((colType.IsGenericType)&&(colType.GetGenericTypeDefinition()==typeof(null)))
{
colType=colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(新数据列(pi.Name,colType));
}
}
DataRow dr=dtReturn.NewRow();
foreach(oProps中的属性信息pi)
{
dr[pi.Name]=pi.GetValue(rec,null)==null?DBNull.Value:pi.GetValue
(rec,空);
}
dtReturn.Rows.Add(dr);
}
返回数据返回;
}

Thx多米尼克。我试过类似的东西。一个巨大的问题——大型实体(即包含大量数据的实体)。为了解决这个问题,我使用了一个递归方法,沿着实体树向下,为它开始复制的每个新级别启动一个新的自身副本(在一个新线程中),但是猜猜看——DataTable对象不是线程安全的。它们的内部索引很容易损坏。当您尝试从多个线程向其中添加行时,就会出现如下异常。我不知道DataTable不是线程安全的。在这种情况下,我想最简单的方法是从SqlCommand填充数据集,而不是从实体传递。有趣的方法。我必须试一下,然后再给你回复。谢谢你的建议。