Datatable select avec plusieurs conditions
j'ai un datatable avec 4 colonnes A, B, C et D Tel qu'une combinaison particulière de valeurs pour les colonnes A, B et c est unique dans le datatable.
Objectif: Pour trouver la valeur de la colonne D, pour une combinaison donnée de valeurs de la colonne A, B et C.
je suppose que boucler sur l'ensemble des lignes de données devrait le faire. Est-il possible d'utiliser Datatable.Sélectionnez() pour accomplir cette? Pour être plus précis-puis - je avoir plusieurs conditions dans le filtre select i.e. des conditions de connexion logiques et opératrices pour chacune des colonnes A, B et C.
7 réponses
Oui,DataTable.Select
la méthode supporte les opérateurs booléens de la même manière que vous les utiliseriez dans une "vraie" instruction SQL:
DataRow[] results = table.Select("A = 'foo' AND B = 'bar' AND C = 'baz'");
Voir DataColumn.Expression in MSDN pour la syntaxe supportée parSelect
méthode.
avez-vous d'utiliser DataTable.Select()
? Je préfère écrire une requête linq pour ce genre de chose.
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");
j'ai trouvé qu'avoir trop d'and's retournerait des résultats incorrects (pour .net 1.1 de toute façon)
DataRow[] results = table.Select("A = 'foo' AND B = 'bar' AND C = 'baz' and D ='fred' and E = 'marg'");
dans mon cas A était le 12e champ dans une table et le select l'ignorait effectivement.
Cependant si je l'ai fait
DataRow[] results = table.Select("A = 'foo' AND (B = 'bar' AND C = 'baz' and D ='fred' and E = 'marg')");
Le filtre a fonctionné correctement!
Essayez ceci,
Je pense que c'est une des solutions 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"]);
assurez-vous, la combinaison des valeurs pour les colonnes A, B et c est unique dans le 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)
où A, B,C sont les noms des colonnes où le second paramètre est pour l'expression sort
si vous ne voulez vraiment pas courir dans beaucoup d'erreurs ennuyeuses (datediff et tels ne peuvent pas être évalués dans DataTable.Select
entre autres choses et même si vous faites comme Utilisation suggérée DataTable.AsEnumerable
vous aurez de la difficulté à évaluer les champs DateTime) faites ce qui suit:
1) modélisez vos données (créez une classe avec des colonnes de données)
Exemple
public class Person
{
public string PersonId { get; set; }
public DateTime DateBorn { get; set; }
}
2) Ajoutez cette classe helper à votre code
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) convertissez facilement votre DataTable
(dt) à une Liste de les objets avec le code suivant:
List<Person> persons = Extensions.ToList<Person>(dt);
4) amusez-vous en utilisant Linq sans lesrow.Field<type>
bits, vous devez utiliser lors de l'utilisation de AsEnumerable
Exemple
var personsBornOn1980 = persons.Where(x=>x.DateBorn.Year == 1980);