2016-02-29 2 views
1

В запросе linq ниже я хотел бы добавить свойство, которое получает предыдущий Department, а также текущий Department. Запрос LINQ ниже возвращается:C# linq получение текущего и предыдущего значения

EffectiveDate EmployeeID Department 
11/4/2012  10   0000 
1/14/2013  10   9121 
2/2/2016  10   9123 

Как я показать предыдущий Department рядом с текущим Department, как это?

EffectiveDate EmployeeID Department PreviousDepartment 
11/4/2012  10   0000  null 
1/14/2013  10   9121  0000 
2/2/2016  10   9123  9121 

Вот текущий запрос

var users = from s in userTable 
      where s.EmployeeID == "10" 
      group new {s} by new { s.EmployeeID, s.Department} into g 
      select new 
      { 
       EffectiveDate = g.Max(m => m.s.EffectiveDate), 
       EmployeeID = g.Key.EmployeeID, 
       Department = g.Key.Department 
       //PreviousDepartment = ??? 
      }; 

спасибо за любую помощь

+0

Есть ли причина, по которой вы делаете 'group new {s}' вместо 'group s'? –

ответ

0

Один из способов сделать это, чтобы сохранить данные в памяти, а затем изменить его, как это:

var users = from s in userTable 
      where s.EmployeeID == "10" 
      group new {s} by new { s.EmployeeID, s.Department} into g 
      select new MyClass 
      { 
       EffectiveDate = g.Max(m => m.s.EffectiveDate), 
       EmployeeID = g.Key.EmployeeID, 
       Department = g.Key.Department 
       PreviousDepartment = null 
      }; 

var result = users.ToList(); 

for(int i = 1; i < result.Count; i++) 
{ 
    result[i].PreviousDepartment = result[i-1].Department; 
} 

Обратите внимание, что код генерирует новые экземпляры MyClass вместо анонимного тип, поскольку свойства анонимного типа доступны только для чтения. Убедитесь, что вы создали такой класс с правильными свойствами.

+0

Спасибо, Якуб. Это выполнило то, что мне нужно. Что касается вашего вопроса о «group new {s}», я использовал это в Linqpad, потому что я получал сообщение об ошибке с «group s». – jaykzoo

0

При использовании интерактивных Extensions (пакет NuGet Ix-Main), вы можете сделать следующее:

var users = 
    userTable 
    .Where(x => x.EmployeeID == "100") 
    .GroupBy(x => new { x.EmployeeID, x.Department }) 
    .Select(x => new 
     { 
      EffectiveDate = x.Max(m => m.EffectiveDate), 
      EmployeeID = x.Key.EmployeeID, 
      Department = x.Key.Department 
     }) 
    .OrderBy(x => x.EffectiveDate) 
    .AsEnumerable() 
    .Scan(
     new 
     { 
      EffectiveDate = default(DateTime), 
      EmployeeID = default(string), 
      Department = default(string), 
      PreviousDepartment = default(string) 
     }, 
     (a, x) => new 
     { 
      EffectiveDate = x.EffectiveDate, 
      EmployeeID = x.EmployeeID, 
      Department = x.Department, 
      PreviousDepartment = a.Department 
     }); 

Преимущество заключается в том, что вы будете с декларативного стиля программирования. Недостатком является то, что он более подробный и, возможно, труднее читать, чем работать с данными в памяти. О, и вам, возможно, придется установить пакет NuGet. Для меня это не проблема, потому что я не думаю, что начинаю проект без добавления Ix-Main.

Ix-Main, никогда не покидайте его без него.

+0

спасибо за ваш ответ, Джейсон. К сожалению, не удается установить расширения в нашей компании, не пропуская много волокиты. – jaykzoo

1

Вы можете создать текущую и предыдущую пару, используя метод Zip в LINQ. Один недостаток заключается в том, что он перечисляет вход дважды (что может быть проблемой, если оно исходит из базы данных), но, с другой стороны, оно не удерживает весь ввод в памяти и является ленивым (т.е. у вас нет потреблять все это).

Например, при использовании INT значения в качестве демо:

[TestMethod] 
public void CurrentAndPrevious() 
{ 
    var input = new int[] { 1, 2, 3, 4, 5 }; 

    var output = Enumerable.Repeat(0,1) // an initial zero value 
     .Concat(input)     // followed by the list 
              // zipped with the list 
     .Zip(input, (x, y) => new {current = y, previous = x}); 

    // a test that passes (using FluentAssertions syntax) 
    string.Join(",", output.Select(x => $"({x.current},{x.previous})")) 
     .Should().Be("(1,0),(2,1),(3,2),(4,3),(5,4)"); 
} 
+0

спасибо за ваш ответ, Ян. Я получаю ошибки при применении этого метода, используя свой список, поэтому нужно будет больше времени смотреть на него. Получите ошибку в методе расширения .Concat, хотя, когда я запускаю ваш код, я этого не делаю. – jaykzoo

0

Метод Синтаксис для достижения.

var result = userTable.Select((x, i) => { Department j = null ; if (i>0) j = userTable.ElementAt(i-1).Department; return new { x.EffectiveDate , x.EmployeeID , x.Department , j};}); 
+0

спасибо за ваше решение, Shashwat, я получаю сообщение об ошибке «Тип или пространство имен не удалось найти», в первой ссылке отдела. – jaykzoo

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