DataColumn: комбинирайте колони и стойности в низ

Бих искал да използвам LINQ, за да взема ред с данни и да анализирам имената на колоните с данни с техните стойности.

Така че, ако имах dataRow със следните колони и стойности:

DataColumn column1 with value '1'
DataColumn column2 with value 'ABC'

Бих искал низът да се върне като "колона1 = '1' и колона2 = 'ABC'"

**** кодът не трябва да се интересува от имената на колоните, нито броя на колоните в таблицата.****

Целта е да се филтрира dataTable като:

var newRows = myTable.Select ("column1 = '1' and column2 = 'ABC'");

Мога да анализирам колоните на таблицата по следния начин:

string[] columnName = myTable.Columns.Cast<DataColumn>().Select(cn => cn.ColumnName).ToArray();

Но трябва също да извлека стойности от целеви ред. Изглежда, че това може да е начало:

{
  string[] columnNames = existingTable.Columns.Cast<DataColumn>().Select(cn => cn.ColumnName).ToArray();
  foreach (DataRow oldRow in existingTable.Rows)
  {
    var criteria = string.Join("and", columnNames, oldRow.ItemArray);
  }
}

person Bill Roberts    schedule 27.05.2015    source източник


Отговори (3)


Мисля, че се опитвате да получите имената на колоните и редовете, без всъщност да ги препращате. Това ли се опитвате да направите:

var table = new DataTable();

var column = new DataColumn {ColumnName = "column1"};
table.Columns.Add(column);

column = new DataColumn {ColumnName = "column2"};
table.Columns.Add(column);

var row = table.NewRow();
row["column1"] = "1";
row["column2"] = "ABC";
table.Rows.Add(row);

string output = "";
foreach (DataRow r in table.Rows)
{
    output = table.Columns.Cast<DataColumn>()
                  .Aggregate(output, (current, c) => current + 
                      string.Format("{0}='{1}' ", c.ColumnName, (string) r[c]));
    output = output + Environment.NewLine;
}

// output should now contain "column1='1' column2='ABC'"

Можете също да създадете методи за разширение от това, които работят както на DataTable (за всички редове), така и на DataRow (за единичен ред):

public static class Extensions
{
    public static string ToText(this DataRow dr)
    {
        string output = "";
        output = dr.Table.Columns.Cast<DataColumn>()
                   .Aggregate(output, (current, c) => current +
                       string.Format("{0}='{1}'", c.ColumnName, (string)dr[c]));

        return output;
    }

    public static string ToText(this DataTable table)
    {
        return table.Rows.Cast<DataRow>()
                    .Aggregate("", (current, dr) => current + dr.ToText() + Environment.NewLine);
    }
}
person Icemanind    schedule 27.05.2015
comment
Благодаря ви, мили господине - успяхте. - person Bill Roberts; 28.05.2015

Бих силно препоръчал картографиране към клас и след това добавяне на друго свойство, което комбинира и двете!

person Michal Ciechan    schedule 27.05.2015
comment
Обикновено бих го направил, но разширявам приложение, което не се поддава добре на тези видове разширения. - person Bill Roberts; 28.05.2015

Вижте дали това ще ви отведе в правилната посока

РЕДАКТИРАНЕ Добавено решение, използващо отражение, тъй като това е по-скоро в съответствие с това, което искате да постигнете

void Main()
{
    List<MyClass> myColl = new List<MyClass>() { new MyClass() { myFirstProp = "1", mySecondProp = "ABC" } };

    foreach (MyClass r in myColl)
    {
        List<string> rPropsAsStrings = new List<string>();

        foreach (PropertyInfo propertyInfo in r.GetType().GetProperties())
        {
            rPropsAsStrings.Add(String.Format("{0} = {1}", propertyInfo.Name, propertyInfo.GetValue(r, null)));
        }

        Console.WriteLine(String.Join(" and ", rPropsAsStrings.ToArray()));
    }


}

public class MyClass
{
    public string myFirstProp { get; set; }
    public string mySecondProp { get; set; }
}

По-долу се използва Linq със силни типизирани свойства

System.Data.DataTable table = new DataTable("ParentTable");
DataColumn column;
DataRow row;

column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "column1";
table.Columns.Add(column);

column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "column2";
table.Columns.Add(column);

row = table.NewRow();
row["column1"] = "1";
row["column2"] = "ABC";
table.Rows.Add(row);

var results = from myRow in table.AsEnumerable()
                select String.Format("column1 = {0}, column2 = {1}", myRow[0], myRow[1]);

foreach (string r in results)
{
    Console.WriteLine(r);
}
person TheRk    schedule 27.05.2015
comment
благодаря за вашия отговор... примерът за код, който предоставих, не изисква познаване на действителните имена на колони и въпреки че не го споменах като изискване, LINQ решение, което мисля, може да направи това. - person Bill Roberts; 28.05.2015
comment
Вероятно също няма да използвате Datatables с linq, беше по-скоро пример, базиран на вашия пример. Предполагам, че използвате linq върху колекция от обект, в който случай със сигурност можете да изключите строго въведените имена чрез зацикляне на свойствата на вашия тип с отражение, но в този момент не linq прави какатенацията, а самият цикъл на отражението. - person TheRk; 28.05.2015
comment
За съжаление в този случай да, използвам LINQ срещу DataTable. Използвам LINQ срещу DT от доста време, според субективните изисквания, разбира се... Благодаря ви отново за помощта;) - person Bill Roberts; 28.05.2015