2014-01-24 2 views
2

Я искал другие вопросы «linq pivot», и я не могу найти точное совпадение для моего. Мне нужно сделать это со всеми анонимными типами. Я пытаюсь отслеживать транзакции проверки с данными, как в следующемСводка с LINQ и анонимным типом?

Check# - Step - Amount 

100 - Book - 100 

100 - Bank - 100 

100 - Account - 100 

101 - Book - 75 

101 - Bank - 75 

101 - Account - NULL 

В результате я ищу, опять же, как анонимный типа:

Check # Book - Bank - Account 

100 - 100 - 100- 100 

101 - 75 - 75 - NULL 

Я действительно не могу сказать если мне нужно сделать группировку первым или нет (по чеку #). Мне нужно, чтобы это было анонимно, потому что я не буду знать имена шагов, как показано здесь. Иногда будет 3 шага, в других случаях их будет намного больше.

+4

Вы хотите, чтобы вы динамически генерировали свойства анонимного типа, исходя из значений времени выполнения? Нет, это не сработает. Вы можете использовать ExpandoObject, потенциально ... –

+0

Начальные значения уже находятся в списке LINQ. Мне нужно преобразовать его с помощью стержня. Я знаю, что свойство STEP есть, я просто не знаю, сколько есть и нужно создать X количество столбцов на основе шагов –

+0

Мне нужно было сделать что-то подобное. [ExpandoObject] (http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject (v = vs.110) .aspx), как уже упоминалось, это единственный способ сделать это. – McAden

ответ

3

Я сделал нечто подобное. Анонимные типы не работали, так как мне приходилось делать столбцы динамически, и анонимные типы все еще должны быть известны во время компиляции. Тем не менее, ExpandoObject позволяет определить свойства во время выполнения.

Я сделал быстрое консольное приложение в качестве доказательства:

using System; 
using System.Collections.Generic; 
using System.Dynamic; 
using System.Linq; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Record> input = new List<Record>(); 
     input.Add(new Record { CheckNumber = 100, Step = "Book", Amount = 100 }); 
     input.Add(new Record { CheckNumber = 100, Step = "Bank", Amount = 100 }); 
     input.Add(new Record { CheckNumber = 100, Step = "Account", Amount = 100 }); 
     input.Add(new Record { CheckNumber = 101, Step = "Book", Amount = 75 }); 
     input.Add(new Record { CheckNumber = 101, Step = "Bank", Amount = 75 }); 
     List<ExpandoObject> results = GetPivotRows(input); 

     //test 
     for (int i = 0; i < results.Count; i++) 
     { 
      dynamic record = results[i]; 
      Console.WriteLine("{0} - {1} - {2} - {3}", record.CheckNumber, record.Book, record.Bank, record.Account); 
     } 
    } 

    public static List<ExpandoObject> GetPivotRows(List<Record> input) 
    { 
     List<string> steps = input.Select(e => e.Step).Distinct().ToList(); 
     Dictionary<int, ExpandoObject> outputMap = new Dictionary<int,ExpandoObject>(); 
     for (int i = 0; i < input.Count; i++) 
     { 
      dynamic row; 
      if(outputMap.ContainsKey(input[i].CheckNumber)) 
      { 
       row = outputMap[input[i].CheckNumber]; 
      } 
      else 
      { 
       row = new ExpandoObject(); 
       row.CheckNumber = input[i].CheckNumber; 
       outputMap.Add(input[i].CheckNumber, row); 

       // Here we're initializing all the possible "Step" columns 
       for (int j = 0; j < steps.Count; j++) 
       { 
        (row as IDictionary<string, object>)[steps[j]] = new Nullable<int>(); 
       } 
      } 

      (row as IDictionary<string, object>)[input[i].Step] = input[i].Amount; 
     } 

     return outputMap.Values.OrderBy(e => ((dynamic)e).CheckNumber).ToList(); 
    } 
} 

public class Record 
{ 
    public int CheckNumber { get; set; } 

    public string Step { get; set; } 

    public decimal Amount { get; set; } 
} 

Выход:

100 - 100 - 100- 100 

101 - 75 - 75 - 

Вы можете использовать отражение для проверки фактических свойств, созданных в процессе.

EDIT: Прояснение это немного - если я изменю, что «тест» петля в основном для:

for (int i = 0; i < results.Count; i++) 
{ 
    Console.WriteLine(string.Join(" - ", results[i])); 
} 

я получаю:

[CheckNumber, 100] - [Book, 100] - [Bank, 100] - [Account, 100] 
[CheckNumber, 101] - [Book, 75] - [Bank, 75] - [Account, ] 

ExpandoObject орудия IDictionary<string, object> за кулисами, чтобы сохранить все, что ему нужно, но в то же время реализует IDynamicMetaObjectProvider и работает с динамической привязкой.

Смежные вопросы