LINQ-запрос и массив строк - PullRequest
       3

LINQ-запрос и массив строк

0 голосов
/ 15 февраля 2012

У меня есть массив string скажем:

String[] Fields=new String[]{RowField,RowField1}

В котором я могу использовать приведенный ниже запрос для получения значений, указав значения, это запрос, т.е. RowField и RowField1:

var Result = (
    from x in _dataTable.AsEnumerable()
    select new
    {
        Name = x.Field<object>(RowField), 
        Name1 = x.Field<object>(RowField1)
    })
    .Distinct();

Но если предположить, что у меня есть много значений в Array, например:

String[] Fields= new String[]
{
    RowField,
    RowField1,
    RowField2,
    .......
    RowField1000
};
  • Как я могу использовать запрос здесь без указания каждого поля строки в запросе?
  • Как я могу перебирать элементы массива внутри LINQ?

Ответы [ 3 ]

3 голосов
/ 15 февраля 2012
var Result = (
    from x in _dataTable.AsEnumerable()
    select (
        from y in Fields
        select new KeyValuePair<string, object>(y, x))
        .ToDictionary())
    .Distinct(DictionariesComparer);

Вам также потребуется написать собственный метод расширения .ToDictionary() и метод DictionariesComparer (так как Dictionary не реализует IEquatable).

2 голосов
/ 15 февраля 2012

По сути, вы хотите получить определенные поля из DataTable без жесткого кодирования имен полей.

Следующий код вернет один объект словаря на строку с полями, указанными в вашем массиве. Нет необходимости создавать дополнительные методы расширения или сравнения:

var result = (from row in _dataTable.AsEnumerable()
                 let projection = from fieldName in fields
                      select new {Name = fieldName, Value = row[fieldName]}
                 select projection.ToDictionary(p=>p.Name,p=>p.Value));            

Внутренний выбор выбирает нужные значения полей из каждой строки таблицы и сохраняет их в переменной проекции. Внешний выбор преобразует эту переменную в словарь

Вы можете перебрать результат, чтобы получить конкретные поля, подобные этим:

foreach (var row in result)
{
    Console.WriteLine(row["field1"]);
}

EDIT: Приведенный выше код не возвращает различные значения. Можно возвращать различные значения без написания специального компаратора, используя группу по , но код не очень красивый:

var result = (from row in table.AsEnumerable()
                let projection = from fieldName in fields
                                select new { Name = fieldName, Value = row[fieldName] }
                group projection by projection.Aggregate((v, p) =>
                    new {
                        Name = v.Name + p.Name, 
                        Value = (object)String.Format("{0}{1}", v.Value, p.Value)
                    }) into g
                select g.FirstOrDefault().ToDictionary(p=>p.Name,p=>p.Value));  

Агрегат создает новую проекцию, свойства имени и значения которой являются объединением всех полей имени и значения. Результат агрегата используется для группировки всех строк и возврата первой строки каждой группы. Это работает, но определенно ужасно.

Было бы лучше создать простой DictionaryComparer, подобный следующему коду:

    public class DictionaryComparer<TKey,TValue>: EqualityComparer<Dictionary<TKey,TValue>>
    {
        public override bool Equals(Dictionary<TKey, TValue> x, Dictionary<TKey, TValue> y)
        {
            //True if both sequences of KeyValuePair items are equal
            var sequenceEqual = x.SequenceEqual(y);
            return sequenceEqual;
        }

        public override int GetHashCode(Dictionary<TKey, TValue> obj)
        {
            //Quickly detect differences in size, defer to Equals for dictionaries 
            //with matching sizes
            return obj.Count;
        }
    }

Это позволяет написать:

        var result = (from row in table.AsEnumerable()
                     let projection = from fieldName in fields
                                      select new {Name = fieldName, Value = row[fieldName]}                                                                                    
                     select projection.ToDictionary(p=>p.Name,p=>p.Value))
                     .Distinct(new DictionaryComparer<string, object>());
0 голосов
/ 15 февраля 2012

Нет выражения foreach linq. Я обычно создаю свой собственный метод расширения

Что-то вроде:

public static void Foreach<T>(this IEnumerable<T> items, Action<T> action)
{
 foreach(T t in items)
 {
  action(t);
 }
}

Однако будьте осторожны, если вы планируете использовать это с Linq2SQL, поскольку это может привести к большому количеству попаданий в БД!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...