返回首页

简介
随着LINQ的到来,有时是更为有用的加载通用的清单,而不是在数据表中的所有数据库中的值。这是因为使用列表更友好,在我看来,在LINQ。本文演示了如何加载的DataTable在任何泛型列表中的任何一个动态的方式。我们将创建两个类,填写查询两个数据表,在两个不同的泛型列表的所有值和负载范围内的数据表。最后,我们将看到一个虚拟的例子; navigationquo​​t LINQ的quot;通过名单。背景
为了使用的代码,它必须有两个重要的事情记:与查询字段相同的属性的名称,您必须定义一个类。属性的数据类型必须是相同的数据字段。使用代码
首先,我们要创建两个表,并填充它们。在这个例子中,创建一个SQL Server数据库,但随意使用任何类型的数据库:

USE [Test]

GO

-- Table [dbo].[EMPLOYEES]

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO



CREATE TABLE [dbo].[EMPLOYEES](

[Name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL,

[Department] [nvarchar](50) COLLATE Latin1_General_CI_AS NULL,

[Salary] [float] NOT NULL,

CONSTRAINT [PK_EMPLOYEES] PRIMARY KEY CLUSTERED 

(

[Name] ASC

)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY]



USE [Test]

GO

--Table [dbo].[CLIENTS] 

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO



CREATE TABLE [dbo].[CLIENTS](

[Id] [int] IDENTITY(1,1) NOT NULL,

[Name] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL,

[Country] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL,

[Address] [nvarchar](50) COLLATE Latin1_General_CI_AS NOT NULL

) ON [PRIMARY]



--Data

INSERT INTO [Test].[dbo].[EMPLOYEES] VALUES ('Peter','Sales',1000)

INSERT INTO [Test].[dbo].[EMPLOYEES] VALUES ('John','Sales',1500)

INSERT INTO [Test].[dbo].[EMPLOYEES] VALUES ('Mary','Orders',1500)

INSERT INTO [Test].[dbo].[EMPLOYEES] VALUES ('Henry',null,3000)

INSERT INTO [Test].[dbo].[CLIENTS] VALUES ('TechEmp','Canada','Unknown')

INSERT INTO [Test].[dbo].[CLIENTS] VALUES ('Ars Inc','Canada','Unknown')

INSERT INTO [Test].[dbo].[CLIENTS] VALUES ('Aslter','Polony','Unknown')

INSERT INTO [Test].[dbo].[CLIENTS] VALUES ('Malper','France','Unknown')

一旦创建和填充表,我们必须声明两个类。这些类将代表我们要加载列表中的表中的行,或者至少是在查询请求的领域的代表性:{C}
正如你可以看到,属性和它们的类型的名称是相同的的表中宣布的领域。
现在,我们要检查的quot; corequot;类。类DataFiller是一个泛型类。这个类的类型将作为quot;登记likequot;类。它会收到一个DataTable,导航思想的DataRow和领域。当循环到达各个领域,它会找到对应的类成员,将分配在属性的正确值。
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data;



//This is neccesary in order to "navigate" 

//throught the class members

using System.Reflection; 

namespace FromDataTableToGenericListExample

{



//In order to return any generic container (in this example is a list)

//,the class must be generic

public class DataFiller<T>

{

    public List<T> FromDataTableToList(DataTable dataTable)

    {

        //This create a new list with the same type of the generic class

        List<T> genericList = new List<T>();

        //Obtains the type of the generic class

        Type t = typeof(T);



        //Obtains the properties definition of the generic class.



        //With this, we are going to know the property names of the class

        PropertyInfo[] pi = t.GetProperties();



        //For each row in the datatable



        foreach (DataRow row in dataTable.Rows)

        {

            //Create a new instance of the generic class

            object defaultInstance = Activator.CreateInstance(t);

            //For each property in the properties of the class

            foreach (PropertyInfo prop in pi)

            {

                try

                {

                    //Get the value of the row according to the field name

                    //Remember that the class茂s members and the table茂s field names

                    //must be identical

                    object columnvalue = row[prop.Name];

                    //Know check if the value is null. 

                    //If not, it will be added to the instance

                    if (columnvalue!= DBNull.Value)

                    {

                        //Set the value dinamically. Now you need to pass as an argument

                        //an instance class of the generic class. This instance has been

                        //created with Activator.CreateInstance(t)

                        prop.SetValue(defaultInstance, columnvalue, null);

                    }

                }

                catch (Exception ex)

                {

                    Console.WriteLine(prop.Name + ": " + ex.ToString());

                    return null;

                }

            }

            //Now, create a class of the same type of the generic class. 

            //Then a conversion it茂s done to set the value

            T myclass = (T)defaultInstance;

            //Add the generic instance to the generic list

            genericList.Add(myclass);

        }

        //At this moment, the generic list contains all de datatable values

        return genericList;

    }

}

}

现在,我们可以运行测试的例子:
你可以下载一个测试项目,以检查它是如何工作的。可以自由离开任何意见或建议。希望有所帮助。

回答

评论会员:Khayralla 时间:2012/01/24
,但我们必须为每个表创建一个类
。是否有可能根据表创建类(动态),以便我们能够避免创建具有相同的名称和类型的类?

感谢
Khayralla
评论会员:圣地亚哥桑切斯 时间:2012/01/24
嗨,很好的问题

我不知道,如果这是可以做到的,与反思,我不知道如何做到这一点。

但是,你的问题让我思考了很多,也许是可以做到以下Visual Studio内的小插件。该插件将一个向导:

1.Connect数据库
2.Allow用户选择的表和字段导入的类 3.Take那些表名和字段名和*. CS到解决方案中,将进口的文件。
是不是100%dinamyc,但将在应用程序需要超过10个班的一些解决方案。

希望有帮助。

关于
评论会员:Khayralla 时间:2012/01/24
一旦你这样做,不forgate送我一份

感谢
Khayralla
评论会员:斯图尔特坎贝尔 时间:2012/01/24
我同意与萨沙,如果你能负担得起的LINQ to SQL在您的项目的开销,我会用,而不是 - 这也意味着你会得到一个方便的方式来执行CRUD操作您的数据,而无需自己写更多的代码..

斯图尔特

appSynergy.com - 模糊您的设备的界限

捕获的公共测试版现已开放!协助我们的用户获取作出的事情
登录{A1}
评论会员:萨沙理发 时间:2012/01/24
LINQ到SQL /实体,在我的DataContext强类型。或者甚至一些DataTable的扩展方法呢?

萨沙理发
微软的Visual C#MVP 2008/2009Codeproject MVP 2008/2009Your最好的朋友就是你。
我是我最好的朋友。我们有着共同的看法,并未落认为

我的博客:{A2}
评论会员:圣地亚哥桑切斯 时间:2012/01/24
当然,你是正确的。他们是非常强大的方式获得的结果,并在LINQ中使用它们。
但是想象一下我的情况。在我的工作,我dont't与SQLServer的工作,所以我不能使用LINQ to SQL。随着实体框架为Oracle的实际版本(我的工作与数据库)是在Beta,所以我很害怕在生产环境中使用它。不喜欢这么多类型的DataSet,导致我们的工作有很多很多的表和其生成类型化数据集向导(我reconize这里,我是一个懒惰的痛苦,但我要保持我的应用程序的向后兼容性)。所以,我必须找到一个简单的方法来加载阵列任何类型的数据表,因为在非类型化数据表的扩展方法是一个小的差,海事组织。

关于
评论会员:。萨沙理发 时间:2012/01/24
够公平,多数民众赞成一个很好的答案。

萨沙理发
微软的Visual C#MVP 2008/2009Codeproject MVP 2008/2009Your最好的朋友就是你。
我是我最好的朋友。我们有着共同的看法,并未落认为

我的博客:{A2}
评论会员:Izzet凯雷姆Kusmezer 时间:2012/01/24
你为什么不使用映射的一部分样本:
http://www.codeproject.com/KB/database/DynamicMethod_ILGenerator.aspx

这将使你的代码运行得更快,因为你不会使用LINQ和对象映射通过反射的反射
评论会员:圣地亚哥桑切斯 时间:2012/01/24
!这是一个很好的文章

我会检查...

关于