from - select into datatable c#
Datatable select con mĂșltiples condiciones (7)
Tengo una tabla de datos con 4 columnas A, B, C y D tal que una combinación particular de valores para la columna A, B y C es única en la tabla de datos.
Objetivo: Encontrar el valor de la columna D para una combinación dada de valores para las columnas A, B y C.
Supongo que debe pasar por encima del conjunto de filas de datos. ¿Hay alguna manera de usar Datatable.Select () para lograr esto? Para ser más específico, ¿puedo tener múltiples condiciones en el filtro de selección, es decir, un operador AND lógico que conecta las condiciones para cada una de las columnas A, B y C.
¿Tienes que usar DataTable.Select()
? Prefiero escribir una consulta de linq para este tipo de cosas.
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");
Descubrí que tener demasiados y devolver resultados incorrectos (para .NET 1.1 de todos modos)
DataRow[] results = table.Select("A = ''foo'' AND B = ''bar'' AND C = ''baz'' and D =''fred'' and E = ''marg''");
En mi caso, A era el 12 ° campo en una tabla y el seleccionado efectivamente lo ignoraba.
Sin embargo, si lo hice
DataRow[] results = table.Select("A = ''foo'' AND (B = ''bar'' AND C = ''baz'' and D =''fred'' and E = ''marg'')");
¡El filtro funcionó correctamente!
Prueba esto,
Creo que esta es una de las soluciones simples.
int rowIndex = table.Rows.IndexOf(table.Select("A = ''foo'' AND B = ''bar'' AND C = ''baz''")[0]);
string strD= Convert.ToString(table.Rows[rowIndex]["D"]);
Asegúrese, la combinación de valores para la columna A, B y C es única en la tabla de datos.
Si realmente no desea encontrarse con muchos errores molestos (dateiff y no se pueden evaluar en DataTable.Select
entre otras cosas e incluso si lo hace como uso sugerido DataTable.AsEnumerable
, tendrá dificultades para evaluar los campos DateTime) do el seguimiento:
1) Modele sus datos (cree una clase con columnas DataTable)
Ejemplo
public class Person
{
public string PersonId { get; set; }
public DateTime DateBorn { get; set; }
}
2) Agregue esta clase de ayuda a su código
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) Convierta fácilmente su DataTable
(dt) a una lista de objetos con el siguiente código:
List<Person> persons = Extensions.ToList<Person>(dt);
4) diviértete usando Linq sin la molesta row.Field<type>
bit que tienes que usar cuando usas AsEnumerable
Ejemplo
var personsBornOn1980 = persons.Where(x=>x.DateBorn.Year == 1980);
Sí, el método DataTable.Select
admite operadores booleanos de la misma manera que los usaría en una declaración SQL "real":
DataRow[] results = table.Select("A = ''foo'' AND B = ''bar'' AND C = ''baz''");
Vea DataColumn.Expression en MSDN para la sintaxis admitida por el método Select
de DataTable.
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)
Donde A, B, C son los nombres de las columnas donde el segundo parámetro es para la expresión de ordenación