列A、B、Cの値の特定の組み合わせがデータテーブル内で一意になるように、4つの列A、B、C、Dを持つデータテーブルがあります。
目的:列A、B、Cの値の特定の組み合わせについて、列Dの値を検索します。
データ行のセットをループ処理する必要があると思います。 Datatable.Select()を使用してこれを達成する方法はありますか?具体的には、選択フィルターに複数の条件、つまり、列A、B、Cのそれぞれの条件を接続する論理AND演算子を使用できますか?.
はい、DataTable.Select
メソッドはブール演算子を「実際の」SQLステートメントで使用するのと同じ方法でサポートします。
DataRow[] results = table.Select("A = 'foo' AND B = 'bar' AND C = 'baz'");
DataTableのSelect
メソッドでサポートされている構文については、 MSDNのDataColumn.Expression を参照してください。
DataTable.Select()
を使用する必要がありますか?私はこの種のことのためにlinqクエリを書くことを好みます。
var dValue= from row in myDataTable.AsEnumerable()
where row.Field<int>("A") == 1
&& row.Field<int>("B") == 2
&& row.Field<int>("C") == 3
select row.Field<string>("D");
が多すぎると、間違った結果が返されることがわかりました(とにかく.NET 1.1の場合)
DataRow[] results = table.Select("A = 'foo' AND B = 'bar' AND C = 'baz' and D ='fred' and E = 'marg'");
私の場合、Aはテーブルの12番目のフィールドであり、selectは事実上それを無視していました。
しかし、私がやった場合
DataRow[] results = table.Select("A = 'foo' AND (B = 'bar' AND C = 'baz' and D ='fred' and E = 'marg')");
フィルターは正常に機能しました!
これを試して、
これは簡単な解決策の1つだと思います。
int rowIndex = table.Rows.IndexOf(table.Select("A = 'foo' AND B = 'bar' AND C = 'baz'")[0]);
string strD= Convert.ToString(table.Rows[rowIndex]["D"]);
列A、B、Cの値の組み合わせがデータテーブルで一意であることを確認してください。
protected void FindCsv()
{
string strToFind = "2";
importFolder = @"C:\Documents and Settings\gmendez\Desktop\";
fileName = "CSVFile.csv";
connectionString= @"Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq="+importFolder+";Extended Properties=Text;HDR=No;FMT=Delimited";
conn = new OdbcConnection(connectionString);
System.Data.Odbc.OdbcDataAdapter da = new OdbcDataAdapter("select * from [" + fileName + "]", conn);
DataTable dt = new DataTable();
da.Fill(dt);
dt.Columns[0].ColumnName = "id";
DataRow[] dr = dt.Select("id=" + strToFind);
Response.Write(dr[0][0].ToString() + dr[0][1].ToString() + dr[0][2].ToString() + dr[0][3].ToString() + dr[0][4].ToString() + dr[0][5].ToString());
}
Dim dr As DataRow()
dr = dt.Select("A="& a & "and B="& b & "and C=" & c,"A",DataViewRowState.CurrentRows)
ここで、A、B、Cは列名で、2番目のパラメーターはソート式用です
本当に多くの迷惑なエラーに遭遇したくない場合(datediffなどは特にDataTable.Select
で評価できず、提案された使用法DataTable.AsEnumerable
で評価しても問題がありますDateTimeフィールド)は次を実行します。
1)データをモデル化する(DataTable列を持つクラスを作成する)
例
public class Person
{
public string PersonId { get; set; }
public DateTime DateBorn { get; set; }
}
2)このヘルパークラスをコードに追加します
public static class Extensions
{
/// <summary>
/// Converts datatable to list<T> dynamically
/// </summary>
/// <typeparam name="T">Class name</typeparam>
/// <param name="dataTable">data table to convert</param>
/// <returns>List<T></returns>
public static List<T> ToList<T>(this DataTable dataTable) where T : new()
{
var dataList = new List<T>();
//Define what attributes to be read from the class
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
//Read Attribute Names and Types
var objFieldNames = typeof(T).GetProperties(flags).Cast<PropertyInfo>().
Select(item => new
{
Name = item.Name,
Type = Nullable.GetUnderlyingType(item.PropertyType) ?? item.PropertyType
}).ToList();
//Read Datatable column names and types
var dtlFieldNames = dataTable.Columns.Cast<DataColumn>().
Select(item => new {
Name = item.ColumnName,
Type = item.DataType
}).ToList();
foreach (DataRow dataRow in dataTable.AsEnumerable().ToList())
{
var classObj = new T();
foreach (var dtField in dtlFieldNames)
{
PropertyInfo propertyInfos = classObj.GetType().GetProperty(dtField.Name);
var field = objFieldNames.Find(x => x.Name == dtField.Name);
if (field != null)
{
if (propertyInfos.PropertyType == typeof(DateTime))
{
propertyInfos.SetValue
(classObj, ConvertToDateTime(dataRow[dtField.Name]), null);
}
else if (propertyInfos.PropertyType == typeof(int))
{
propertyInfos.SetValue
(classObj, ConvertToInt(dataRow[dtField.Name]), null);
}
else if (propertyInfos.PropertyType == typeof(long))
{
propertyInfos.SetValue
(classObj, ConvertToLong(dataRow[dtField.Name]), null);
}
else if (propertyInfos.PropertyType == typeof(decimal))
{
propertyInfos.SetValue
(classObj, ConvertToDecimal(dataRow[dtField.Name]), null);
}
else if (propertyInfos.PropertyType == typeof(String))
{
if (dataRow[dtField.Name].GetType() == typeof(DateTime))
{
propertyInfos.SetValue
(classObj, ConvertToDateString(dataRow[dtField.Name]), null);
}
else
{
propertyInfos.SetValue
(classObj, ConvertToString(dataRow[dtField.Name]), null);
}
}
}
}
dataList.Add(classObj);
}
return dataList;
}
private static string ConvertToDateString(object date)
{
if (date == null)
return string.Empty;
return HelperFunctions.ConvertDate(Convert.ToDateTime(date));
}
private static string ConvertToString(object value)
{
return Convert.ToString(HelperFunctions.ReturnEmptyIfNull(value));
}
private static int ConvertToInt(object value)
{
return Convert.ToInt32(HelperFunctions.ReturnZeroIfNull(value));
}
private static long ConvertToLong(object value)
{
return Convert.ToInt64(HelperFunctions.ReturnZeroIfNull(value));
}
private static decimal ConvertToDecimal(object value)
{
return Convert.ToDecimal(HelperFunctions.ReturnZeroIfNull(value));
}
private static DateTime ConvertToDateTime(object date)
{
return Convert.ToDateTime(HelperFunctions.ReturnDateTimeMinIfNull(date));
}
}
public static class HelperFunctions
{
public static object ReturnEmptyIfNull(this object value)
{
if (value == DBNull.Value)
return string.Empty;
if (value == null)
return string.Empty;
return value;
}
public static object ReturnZeroIfNull(this object value)
{
if (value == DBNull.Value)
return 0;
if (value == null)
return 0;
return value;
}
public static object ReturnDateTimeMinIfNull(this object value)
{
if (value == DBNull.Value)
return DateTime.MinValue;
if (value == null)
return DateTime.MinValue;
return value;
}
/// <summary>
/// Convert DateTime to string
/// </summary>
/// <param name="datetTime"></param>
/// <param name="excludeHoursAndMinutes">if true it will execlude time from datetime string. Default is false</param>
/// <returns></returns>
public static string ConvertDate(this DateTime datetTime, bool excludeHoursAndMinutes = false)
{
if (datetTime != DateTime.MinValue)
{
if (excludeHoursAndMinutes)
return datetTime.ToString("yyyy-MM-dd");
return datetTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
}
return null;
}
}
3)次のコードを使用して、DataTable
(dt)をオブジェクトのリストに簡単に変換します。
List<Person> persons = Extensions.ToList<Person>(dt);
4)AsEnumerable
を使用するときに使用しなければならない面倒なrow.Field<type>
ビットなしでLinqを使用して楽しんでください
例
var personsBornOn1980 = persons.Where(x=>x.DateBorn.Year == 1980);