如何将DataTable转换为类Object

ami*_*tel 31 .net c# linq asp.net datatable

我已经开发了一个可以在任何地方返回DataTable的应用程序.

现在我的客户端想要转换(使用服务堆栈使用某些部分),所以我需要在我的应用程序中返回DTO(对象).

我不想更改现有的存储过程,甚至不想尽可能多地使用LINQ(我对LINQ并不太了解).

对于小功能,我可以使用Linq没问题.

我的问题是:我如何改变我DataTable对该类的对象?

示例代码如下

string s = DateTime.Now.ToString();
DataTable dt = new DataTable();

dt.Columns.Add("id");
dt.Columns.Add("name");

for (int i = 0; i < 5000000; i++)
{
    DataRow dr = dt.NewRow();
    dr["id"] = i.ToString();
    dr["name"] = "name" + i.ToString();
    dt.Rows.Add(dr);

    dt.AcceptChanges();
}

List<Class1> clslist = new List<Class1>();

for (int i = 0; i < dt.Rows.Count; i++)
{
    Class1 cls = new Class1();
    cls.id = dt.Rows[i]["id"].ToString();
    cls.name = dt.Rows[i]["name"].ToString();
    clslist.Add(cls);
}

Response.Write(s);
Response.Write("<br>");
Response.Write(DateTime.Now.ToString());
Run Code Online (Sandbox Code Playgroud)

我知道,上面是耗时的,所以我试图找到一个替代解决方案.

有没有其他方法(我猜,LINQ to DataTable),通过它直接将表行转换为DTO (objects)

所以我可以在服务堆栈中返回对象并继续.

sll*_*sll 71

初始化DataTable:

DataTable dt = new DataTable(); 
dt.Columns.Add("id", typeof(String)); 
dt.Columns.Add("name", typeof(String)); 
for (int i = 0; i < 5; i++)
{
    string index = i.ToString();
    dt.Rows.Add(new object[] { index, "name" + index });
}
Run Code Online (Sandbox Code Playgroud)

查询本身:

IList<Class1> items = dt.AsEnumerable().Select(row => 
    new Class1
        {
            id = row.Field<string>("id"),
            name = row.Field<string>("name")
        }).ToList();
Run Code Online (Sandbox Code Playgroud)


Bha*_*rat 11

阿米特,我用一种方法用更少的编码和更有效的方式实现这一目标.

但它使用Linq.

我在这里发布了它,因为答案可能有助于其他SO.

DAL代码下面将数据表对象转换为List of YourViewModel,并且很容易理解.

public static class DAL
{
        public static string connectionString = ConfigurationManager.ConnectionStrings["YourWebConfigConnection"].ConnectionString;

        // function that creates a list of an object from the given data table
        public static List<T> CreateListFromTable<T>(DataTable tbl) where T : new()
        {
            // define return list
            List<T> lst = new List<T>();

            // go through each row
            foreach (DataRow r in tbl.Rows)
            {
                // add to the list
                lst.Add(CreateItemFromRow<T>(r));
            }

            // return the list
            return lst;
        }

        // function that creates an object from the given data row
        public static T CreateItemFromRow<T>(DataRow row) where T : new()
        {
            // create a new object
            T item = new T();

            // set the item
            SetItemFromRow(item, row);

            // return 
            return item;
        }

        public static void SetItemFromRow<T>(T item, DataRow row) where T : new()
        {
            // go through each column
            foreach (DataColumn c in row.Table.Columns)
            {
                // find the property for the column
                PropertyInfo p = item.GetType().GetProperty(c.ColumnName);

                // if exists, set the value
                if (p != null && row[c] != DBNull.Value)
                {
                    p.SetValue(item, row[c], null);
                }
            }
        }

        //call stored procedure to get data.
        public static DataSet GetRecordWithExtendedTimeOut(string SPName, params SqlParameter[] SqlPrms)
        {
            DataSet ds = new DataSet();
            SqlCommand cmd = new SqlCommand();
            SqlDataAdapter da = new SqlDataAdapter();
            SqlConnection con = new SqlConnection(connectionString);

            try
            {
                cmd = new SqlCommand(SPName, con);
                cmd.Parameters.AddRange(SqlPrms);
                cmd.CommandTimeout = 240;
                cmd.CommandType = CommandType.StoredProcedure;
                da.SelectCommand = cmd;
                da.Fill(ds);
            }
            catch (Exception ex)
            {
               return ex;
            }

            return ds;
        }
}
Run Code Online (Sandbox Code Playgroud)

现在,传递和调用方法的方法如下.

    DataSet ds = DAL.GetRecordWithExtendedTimeOut("ProcedureName");

    List<YourViewModel> model = new List<YourViewModel>();

    if (ds != null)
    {
        //Pass datatable from dataset to our DAL Method.
        model = DAL.CreateListFromTable<YourViewModel>(ds.Tables[0]);                
    }      
Run Code Online (Sandbox Code Playgroud)

到目前为止,对于我的许多应用程序,我发现这是获取数据的最佳结构.

  • 这不起作用。https://dotnetfiddle.net/x5dtGA 还应注意反射非常慢,不应用于性能关键代码。 (4认同)

小智 9

看着这个并意识到:它是从一种类型的对象到另一种类型的对象;基本上我们正在努力进行适当的反思。

有适当的方法来构建不同字段之间的关系,但是只要完成类定义,就可以通过 Newtonsoft.Json 轻松完成

流程:DataSet/DataTable(序列化)==> Json(反序列化)==> 目标对象列表 在此示例中作为OP,只需执行以下操作:

string serializeddt = JsonConvert.SerializeObject(dt, Formatting.Indented);
Run Code Online (Sandbox Code Playgroud)

现在 DataTable 被序列化为纯字符串。然后执行以下操作:

List<Class1> clslist = JsonConvert.DeserializeObject<List<Class1>>(serialized, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
Run Code Online (Sandbox Code Playgroud)

现在您应该拥有一个列表,其中所有 DataTable 行作为单独的对象。