Как преобразовать DataTable в класс Object?
Я уже разработал приложение, которое возвращает DataTable
везде.
Теперь мой клиент хочет преобразовать (использовать некоторую часть, используя стек служб), поэтому мне нужно вернуть DTO (objects)
в моем приложении.
Я не хочу менять свои существующие хранимые процедуры или даже не хочу использовать 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());
Я знаю, что описанный выше метод занимает много времени, и я пытаюсь найти альтернативное решение.
Есть ли какой-нибудь альтернативный способ (я думаю, LINQ to DataTable), с помощью которого он напрямую преобразует строки таблиц в List<Class1>
?
Так что я могу вернуть объекты в моем стеке услуг и идти вперед.
Ответы
Ответ 1
Инициализировать 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 });
}
Сам запрос:
IList<Class1> items = dt.AsEnumerable().Select(row =>
new Class1
{
id = row.Field<string>("id"),
name = row.Field<string>("name")
}).ToList();
Ответ 2
Amit, я использовал один способ добиться этого с меньшим количеством кодирования и более эффективным способом.
но он использует Linq.
Я разместил его здесь, потому что, возможно, ответ помогает другим SO.
Ниже код DAL преобразует объект datatable в список 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;
}
}
Теперь способ передачи и вызова метода ниже.
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]);
}
До даты, для многих моих приложений, я нашел это как лучшую структуру для получения данных.
Ответ 3
Это версия Vb.Net:
Public Class Test
Public Property id As Integer
Public Property name As String
Public Property address As String
Public Property createdDate As Date
Конец класса
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim x As Date = Now
Debug.WriteLine("Begin: " & DateDiff(DateInterval.Second, x, Now) & "-" & Now)
Dim dt As New DataTable
dt.Columns.Add("id")
dt.Columns.Add("name")
dt.Columns.Add("address")
dt.Columns.Add("createdDate")
For i As Integer = 0 To 100000
dt.Rows.Add(i, "name - " & i, "address - " & i, DateAdd(DateInterval.Second, i, Now))
Next
Debug.WriteLine("Datatable created: " & DateDiff(DateInterval.Second, x, Now) & "-" & Now)
Dim items As IList(Of Test) = dt.AsEnumerable().[Select](Function(row) New _
Test With {
.id = row.Field(Of String)("id"),
.name = row.Field(Of String)("name"),
.address = row.Field(Of String)("address"),
.createdDate = row.Field(Of String)("createdDate")
}).ToList()
Debug.WriteLine("List created: " & DateDiff(DateInterval.Second, x, Now) & "-" & Now)
Debug.WriteLine("Complated")
End Sub
Ответ 4
Возможно, вам стоит взглянуть на код здесь. Хотя он не отвечает на ваш вопрос напрямую, вы можете адаптировать общие типы классов, которые используются для сопоставления между классами данных и бизнес-объектами.
Также, используя generic, вы запускаете процесс преобразования как можно быстрее.