現在、私は使用しています:
DataTable dt = CreateDataTableInSomeWay();
List<DataRow> list = new List<DataRow>();
foreach (DataRow dr in dt.Rows)
{
list.Add(dr);
}
より良い/魔法の方法はありますか?
.NET 3.5 を使用している場合は、DataTableExtensions.AsEnumerable
(拡張メソッド) を使用できます。必要な場合は、単に呼び出すList<DataRow>
だけではなく、次のようにします。IEnumerable<DataRow>
Enumerable.ToList
IEnumerable<DataRow> sequence = dt.AsEnumerable();
また
using System.Linq;
...
List<DataRow> list = dt.AsEnumerable().ToList();
List<Employee> emp = new List<Employee>();
//Maintaining DataTable on ViewState
//For Demo only
DataTable dt = ViewState["CurrentEmp"] as DataTable;
//read data from DataTable
//using lamdaexpression
emp = (from DataRow row in dt.Rows
select new Employee
{
_FirstName = row["FirstName"].ToString(),
_LastName = row["Last_Name"].ToString()
}).ToList();
C# 3.0 と System.Data.DataSetExtensions.dll を使用すると、
List<DataRow> rows = table.Rows.Cast<DataRow>().ToList();
あなたが使用することができます
List<DataRow> list = new List<DataRow>(dt.Select());
dt.Select()
テーブル内のすべての行をデータ行の配列として返し、List
コンストラクターはそのオブジェクトの配列を引数として受け取り、最初にリストに入力します。
次のように拡張機能を作成できます。
public static List<T> ToListof<T>(this DataTable dt)
{
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
var columnNames = dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.ToList();
var objectProperties = typeof(T).GetProperties(flags);
var targetList = dt.AsEnumerable().Select(dataRow =>
{
var instanceOfT = Activator.CreateInstance<T>();
foreach (var properties in objectProperties.Where(properties => columnNames.Contains(properties.Name) && dataRow[properties.Name] != DBNull.Value))
{
properties.SetValue(instanceOfT, dataRow[properties.Name], null);
}
return instanceOfT;
}).ToList();
return targetList;
}
var output = yourDataInstance.ToListof<targetModelType>();
「ID」intフィールドの値のリストを返すだけの場合は、...を使用できます。
List<int> ids = (from row in dt.AsEnumerable() select Convert.ToInt32(row["ID"])).ToList();
null 許容型の場合は例外が返されるため、この回答 ( https://stackoverflow.com/a/24588210/4489664 )のコードにいくつかの変更を加えました。
public static List<T> DataTableToList<T>(this DataTable table) where T: new()
{
List<T> list = new List<T>();
var typeProperties = typeof(T).GetProperties().Select(propertyInfo => new
{
PropertyInfo = propertyInfo,
Type = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType
}).ToList();
foreach (var row in table.Rows.Cast<DataRow>())
{
T obj = new T();
foreach (var typeProperty in typeProperties)
{
object value = row[typeProperty.PropertyInfo.Name];
object safeValue = value == null || DBNull.Value.Equals(value)
? null
: Convert.ChangeType(value, typeProperty.Type);
typeProperty.PropertyInfo.SetValue(obj, safeValue, null);
}
list.Add(obj);
}
return list;
}
using System.Data;
var myEnumerable = myDataTable.AsEnumerable();
List<MyClass> myClassList =
(from item in myEnumerable
select new MyClass{
MyClassProperty1 = item.Field<string>("DataTableColumnName1"),
MyClassProperty2 = item.Field<string>("DataTableColumnName2")
}).ToList();
繰り返しますが、3.5 を使用すると、次のようにすることができます。
dt.Select().ToList()
BRGDS
// this is better suited for expensive object creation/initialization
IEnumerable<Employee> ParseEmployeeTable(DataTable dtEmployees)
{
var employees = new ConcurrentBag<Employee>();
Parallel.ForEach(dtEmployees.AsEnumerable(), (dr) =>
{
employees.Add(new Employee()
{
_FirstName = dr["FirstName"].ToString(),
_LastName = dr["Last_Name"].ToString()
});
});
return employees;
}
より「魔法の」方法であり、.NET 3.5 は必要ありません。
たとえば、DBDatatable
Guids (SQL では一意の識別子) の単一の列を返す場合は、次を使用できます。
Dim gList As New List(Of Guid)
gList.AddRange(DirectCast(DBDataTable.Select(), IEnumerable(Of Guid)))
DataTable.Select()
データテーブルに存在する順序で行を提供しません。
順序が重要な場合は、データ行コレクションを反復処理してリストを作成するのが正しい方法だと思います。または、オーバーロードを使用することもできますDataTable.Select(string filterexpression, string sort)
。
ただし、このオーバーロードは、SQL が提供するすべての順序付け (ケースごとの順序など) を処理できない場合があります。
DataTable dt; // datatable should contains datacolumns with Id,Name
List<Employee> employeeList=new List<Employee>(); // Employee should contain EmployeeId, EmployeeName as properties
foreach (DataRow dr in dt.Rows)
{
employeeList.Add(new Employee{EmployeeId=dr.Id,EmplooyeeName=dr.Name});
}
System.Data
名前空間を使用すると、 が得られ.AsEnumerable()
ます。
手動で aをに変換DataTable
するList
代わりに、ジェネリック メソッドを使用して に変換できます。DataTable
List
注:DataTable
とは同じである必要がありますColumnName
。Type
PropertyName
以下のメソッドを呼び出します。
long result = Utilities.ConvertTo<Student>(dt ,out listStudent);
// Generic Method
public class Utilities
{
public static long ConvertTo<T>(DataTable table, out List<T> entity)
{
long returnCode = -1;
entity = null;
if (table == null)
{
return -1;
}
try
{
entity = ConvertTo<T>(table.Rows);
returnCode = 0;
}
catch (Exception ex)
{
returnCode = 1000;
}
return returnCode;
}
static List<T> ConvertTo<T>(DataRowCollection rows)
{
List<T> list = null;
if (rows != null)
{
list = new List<T>();
foreach (DataRow row in rows)
{
T item = CreateItem<T>(row);
list.Add(item);
}
}
return list;
}
static T CreateItem<T>(DataRow row)
{
string str = string.Empty;
string strObj = string.Empty;
T obj = default(T);
if (row != null)
{
obj = Activator.CreateInstance<T>();
strObj = obj.ToString();
NameValueCollection objDictionary = new NameValueCollection();
foreach (DataColumn column in row.Table.Columns)
{
PropertyInfo prop = obj.GetType().GetProperty(column.ColumnName);
if (prop != null)
{
str = column.ColumnName;
try
{
objDictionary.Add(str, row[str].ToString());
object value = row[column.ColumnName];
Type vType = obj.GetType();
if (value == DBNull.Value)
{
if (vType == typeof(int) || vType == typeof(Int16)
|| vType == typeof(Int32)
|| vType == typeof(Int64)
|| vType == typeof(decimal)
|| vType == typeof(float)
|| vType == typeof(double))
{
value = 0;
}
else if (vType == typeof(bool))
{
value = false;
}
else if (vType == typeof(DateTime))
{
value = DateTime.MaxValue;
}
else
{
value = null;
}
prop.SetValue(obj, value, null);
}
else
{
prop.SetValue(obj, value, null);
}
}
catch(Exception ex)
{
}
}
}
PropertyInfo ActionProp = obj.GetType().GetProperty("ActionTemplateValue");
if (ActionProp != null)
{
object ActionValue = objDictionary;
ActionProp.SetValue(obj, ActionValue, null);
}
}
return obj;
}
}
これは私にとってはうまくいきました: 少なくとも.Net Framework 3.5が必要 です。以下のコードは、DataRowがGeneric.IEnumerableに変わったことを示しています。より良い説明のためにcomboBox1が使用されています。
using System.Linq;
DataTable dt = new DataTable();
dt = myClass.myMethod();
List<object> list = (from row in dt.AsEnumerable() select (row["name"])).ToList();
comboBox1.DataSource = list;
誰かがデータテーブルをリストに変換するカスタム関数を作成したい場合
class Program
{
static void Main(string[] args)
{
DataTable table = GetDataTable();
var sw = new Stopwatch();
sw.Start();
LinqMethod(table);
sw.Stop();
Console.WriteLine("Elapsed time for Linq Method={0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
ForEachMethod(table);
sw.Stop();
Console.WriteLine("Elapsed time for Foreach method={0}", sw.ElapsedMilliseconds);
Console.ReadKey();
}
private static DataTable GetDataTable()
{
var table = new DataTable();
table.Columns.Add("ID", typeof(double));
table.Columns.Add("CategoryName", typeof(string));
table.Columns.Add("Active", typeof(double));
var rand = new Random();
for (int i = 0; i < 100000; i++)
{
table.Rows.Add(i, "name" + i, rand.Next(0, 2));
}
return table;
}
private static void LinqMethod(DataTable table)
{
var list = table.AsEnumerable()
.Skip(1)
.Select(dr =>
new Category
{
Id = Convert.ToInt32(dr.Field<double>("ID")),
CategoryName = dr.Field<string>("CategoryName"),
IsActive =
dr.Field<double>("Active") == 1 ? true : false
}).ToList();
}
private static void ForEachMethod(DataTable table)
{
var categoryList = new List<Category>(table.Rows.Count);
foreach (DataRow row in table.Rows)
{
var values = row.ItemArray;
var category = new Category()
{
Id = Convert.ToInt32(values[0]),
CategoryName = Convert.ToString(values[1]),
IsActive = (double)values[2] == 1 ? true : false
};
categoryList.Add(category);
}
}
private class Category
{
public int Id { get; set; }
public string CategoryName { get; set; }
public bool IsActive { get; set; }
}
}
上記のコードを実行すると、Foreach メソッドは 56 ミリ秒で終了しますが、linq メソッドは 101 ミリ秒 (1000 レコード) かかります。したがって、Foreach メソッドを使用することをお勧めします。出典: C# で Datatable を List に変換する方法 (パフォーマンス テストの例あり)
次の2つの汎用関数を使用できます
private static List<T> ConvertDataTable<T>(DataTable dt)
{
List<T> data = new List<T>();
foreach (DataRow row in dt.Rows)
{
T item = GetItem<T>(row);
data.Add(item);
}
return data;
}
private static T GetItem<T>(DataRow dr)
{
Type temp = typeof(T);
T obj = Activator.CreateInstance<T>();
foreach (DataColumn column in dr.Table.Columns)
{
foreach (PropertyInfo pro in temp.GetProperties())
{
if (pro.Name == column.ColumnName)
pro.SetValue(obj, dr[column.ColumnName].ToString(), null);
else
continue;
}
}
return obj;
}
そしてそれを次のように使用します
List<StudentScanExamsDTO> studentDetails = ConvertDataTable<StudentScanExamsDTO>(dt);