2010-01-02 147 views
36

我有4列A,B,C和d的DataTable,使得對於列A,B和C值的特定組合在數據表是唯一的。數據表選擇與多個條件

目的:爲了找到列d的值,我估計循環通過所述一組數據行應該這樣做的列A,B和C.

值的給定組合。有沒有辦法使用Datatable.Select()來完成這個?更具體地說 - 我可以在選擇過濾器中有多個條件,即每列A,B和C的邏輯AND運算符連接條件。

+0

所以柱d是計算列的基礎上,A,B,和C? – 2010-01-02 08:08:35

+0

你有沒有考慮過將它作爲查詢發出,並讓數據庫執行它的功能? – 2010-01-02 08:09:29

回答

88

是的,DataTable.Select方法支持以同樣的方式布爾運算,你會使用他們在一個「真正的」 SQL語句:

DataRow[] results = table.Select("A = 'foo' AND B = 'bar' AND C = 'baz'"); 

由DataTable的Select方法支持的語法見DataColumn.Expression in MSDN

31

您是否必須使用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"); 
+0

凌空風格的LINQ + 1選擇過濾器表達式 – 2014-10-14 06:59:23

6

我發現有太多的和的將返回不正確的結果(.NET 1.1反正)

DataRow[] results = table.Select("A = 'foo' AND B = 'bar' AND C = 'baz' and D ='fred' and E = 'marg'"); 

在我的情況下A是在一個表中的第12場和選擇得到有效忽略它。

但是,如果我做了

DataRow[] results = table.Select("A = 'foo' AND (B = 'bar' AND C = 'baz' and D ='fred' and E = 'marg')"); 

過濾器工作正常!

+0

這必須是一些錯誤的種類。你的兩個例子在邏輯上沒有區別。 – Christian 2017-09-25 10:51:12

2
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()); 
    } 
5

試試這個,
我想,這是一個簡單的解決方案之一。

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的值的組合在數據表中是唯一的。

+0

您的解決方案'int rowIndex = ... [0]'只能返回匹配的第一行,即使請求返回一個「唯一」值,也可能有多個值被忽略。爲什麼不'int [] rowIndex = ...'並返回任何結果。重點在於,如果所謂的獨特組合不是唯一的,並且存在數據錯誤,那麼它可以得到補救。 – LokizFenrir 2015-05-20 07:09:01

1
Dim dr As DataRow() 


dr = dt.Select("A="& a & "and B="& b & "and C=" & c,"A",DataViewRowState.CurrentRows) 

其中A,B,C是列名 這裏如果你真的不想碰到很多煩人的錯誤(DATEDIFF和這樣不能第二個參數是排序表達式

0

尤其在DataTable.Select進行評估,即使你的建議使用DataTable.AsEnumerable你會遇到麻煩評估日期時間字段),請執行以下操作:

1)型號您的數據(創建數據表列一類)

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)在使用Linq時沒有煩人的row.Field<type>位,您必須使用AsEnumerable

var personsBornOn1980 = persons.Where(x=>x.DateBorn.Year == 1980);