2009-12-11 4 views
3

다른 소스에서 이벤트를 표시하지만 시간 스탬프로 정렬 된 로그 뷰어를 만들려고합니다. 나는 이걸로 C# Linq를 사용할 수있는 벌칙을 가졌지 만 어떻게해야합니까?Linq 다른 종류의 목록을 정렬하려면

예 : 파일에서 읽은 이벤트 목록 하나가 날짜/시간 스탬프로 정렬 된 스트라이프 목록에 있습니다.

또 다른 이벤트 소스는 Linq를 사용하여 첫 번째 목록과 동일한 시간 세그먼트를 추출하는 데이터베이스 삽입입니다. 데이터베이스에는 또한 시간 소인이 있습니다.

내가 원하는 것은 실시간으로 일어나는 모든 이벤트를 나열한 목록을 보여주는 것입니다. 즉, dabase 삽입은 초 후에 디스크 파일에 기록 된 예외로 이어질 수 있습니다.

나는 하나의 공통 필드 타임 스탬프를 공유하는 목록에 이들을 조인하고 정렬하는 방법을 찾고있다. 각 요소가 다른 종류 일지라도 foreach를 사용할 수있는 컬렉션으로 끝난다.

어떤 아이디어?

마틴

답변

1

Linq를 사용하여 두 데이터 소스를 동일한 유형으로 변환 한 다음 결합하여 정렬 할 수 있습니다. 여기에 타임 스탬프 필드와 다른 필드가있는 T_Log 데이터베이스의 개체가 있고 다른 소스가 있습니다. 각 문자열에 줄의 시작 부분에 타임 스탬프가 들어있는 가짜 파일의 문자열. 둘 다 사용자 지정 클래스로 변환했습니다.다음이 정렬하는 데 사용됩니다. CommonLog에는 원본 개체에 대한 참조가 포함되어 있으므로 자세한 정보가 필요하면 해당 정보를 전송하고 가져올 수 있습니다.

더 가볍고 구현은 KeyValuePair<DateTime, object>로, 이미 존재하는 클래스 등을 변환 할 수 있습니다. 여기

코드입니다 :

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

class Program 
{  
    // Fake database class. 
    class T_Log 
    { 
     public DateTime Timestamp { get; set; } 
     public string Info { get; set; } 
     public int Priority { get; set; } 
    } 

    static void Main(string[] args) 
    { 
     // Create some events in the fake database. 
     List<T_Log> dbLogs = new List<T_Log> { 
      new T_Log { Timestamp = new DateTime(2009, 2, 5), Info = "db: foo", Priority = 1 }, 
      new T_Log { Timestamp = new DateTime(2009, 2, 9), Info = "db: bar", Priority = 2 } 
     }; 

     // Create some lines in a fake file. 
     List<string> fileLogs = new List<string> { 
      "2009-02-06: File foo", 
      "2009-02-10: File bar" 
     }; 


     var logFromDb = 
      dbLogs.Select(x => new CommonLog(
          x.Timestamp, 
          string.Format("{1} [Priority={2}]", 
             x.Timestamp, 
             x.Info, 
             x.Priority), 
          x)); 

     var logFromFile = 
      fileLogs.Select(x => new CommonLog(
          DateTime.Parse(x.Substring(0, x.IndexOf(':'))), 
          x.Substring(x.IndexOf(':') + 2), 
          x 
       )); 

     var combinedLog = logFromDb.Concat(logFromFile).OrderBy(x => x.Timestamp); 
     foreach (var logEntry in combinedLog) 
      Console.WriteLine("{0}: {1}", logEntry.Timestamp, logEntry.Log); 
    } 
} 

// This class is used to store logs from any source. 
class CommonLog 
{ 
    public CommonLog(DateTime timestamp, 
        string log, 
        object original) 
    { 
     this.Timestamp = timestamp; 
     this.Log = log; 
     this.Original = original; 
    } 

    public DateTime Timestamp { get; private set; } 
    public string Log { get; private set; } 
    public object Original { get; private set; } 
} 

출력 :

05-02-2009 00:00:00: db: foo [Priority=0] 
06-02-2009 00:00:00: file: baz 
09-02-2009 00:00:00: db: bar [Priority=0] 
10-02-2009 00:00:00: file: quux 

업데이트 : 마틴이 게시물에 대한 코멘트에 다음과 같은 대답하지만, 때문에 의견 포맷의 부족 읽기가 힘들었다 . 여기에 서식이 있습니다 :

var ld = rs.Select(x => new KeyValuePair<DateTime, object>(DateTime.Parse(x[0]), x)) 
      .Concat(ta.Select(y => new KeyValuePair<DateTime, object>(y.Tidspunkt, y))) 
      .OrderBy(d => d.Key); 
+0

감사합니다.지금은 그냥 여기 조금을 선택했고 거기는 :) 작업을 진행하게 내 첫 번째 목록은 목록 는 두 번째 목록은 하나 개의 요소 결합 날짜 시간 있는 테이블 클래스이었다 [0] s의 타임 스탬프와 함께했다으로 모두 내가 결국 : var ld = rs.Select (x => 새 KeyValuePair (DateTime.Parse (x [0]), x)) .Concat (ta.Select (y => new KeyValuePair (y.Tidspunkt, y))).) OrderBy (d => d.Key); 그리고 값 유형은 다형성과 같이 (LD에 var에 m) { (m.Value이 Nettbud이다) 경우 ... 다른 ... } 우리가 알려 주셔서 마틴 – Martin

+0

감사 foreach는 어떻게 지내? 그리고 답을 수락하는 것을 잊지 마십시오. :) –

+0

미안하지만 여기는 처음입니다. 포맷에 대한 지침을 볼 수없고, 600chars를 확장하고 마킹에 응답 할 수 없습니다! Martin – Martin

1

내가 코드가 아래에이 찾고있는 무엇을 달성한다고 생각합니다.

은 기본적으로 당신은 단지 개체의 목록을 만든 다음 그 목록에 DB & 파일 로그 귀하의 목록을 추가해야합니다. 위의 코드는 (가정 LogItem는 @ 마크 바이어스에서 같은 컨테이너 클래스입니다 아래의 코드를 사용하여 개선 할 수있는 응답 :이 완료되고 나면이 정렬

List<Db> db_inserts = new List<Db>(); 
    // populate list of db events here 

    List<Fi> files = new List<Fi>(); 
    // populate list of file events here 

    List<object> all = new List<object>(); 
    all.AddRange(db_inserts.Cast<object>()); 
    all.AddRange(files.Cast<object>()); 

    // sort the list by time 
    all.Sort(delegate(object a, object b) 
    { 
     DateTime aTime = DateTime.MinValue; 
     DateTime bTime = DateTime.MinValue; 

     if (a is Db) 
      aTime = ((Db)a).time; 
     else if (a is Fi) 
      aTime = ((Fi)a).time; 

     if (b is Db) 
      bTime = ((Db)b).time; 
     else if (b is Fi) 
      bTime = ((Fi)b).time; 

     return aTime.CompareTo(bTime); 
    }); 

편집을 처리 할 대리자를 쓸 수

List<LogItem> all = new List<LogItem>(); 
    all.AddRange(db_inserts.Select(x => new LogItem { time = x.time, msg = x.name, source=x})); 
    all.AddRange(files.Select(x => new LogItem{time = x.time, msg = x.name, source = x})); 

    var query = all.OrderBy(x => x.time); 
1

로그 소스를 연결 한 다음 결과를 정렬하십시오. 각 로그 소스를 가정하면 IEnumerable<LogEntry> :

var logSources = new [] 
{ 
    GetFileLogs(), 
    GetDbLogs() 
    // whatever other sources you need... 
}; 

var entries = Enumerable.Empty<LogEntry>(); 
foreach (var source in logSources) 
{ 
    entries = entries.Concat(source); 
} 

entries = entries.OrderBy(e => e.Timestamp); 
관련 문제