OData (Open Data Protocol) 為 Microsoft 推動的開放資料存取標準,基於 HTTP、AtomPub、JSON。本文示範以 WCF Data Services 搭配 Reflection Provider,將伺服器的 Windows 應用程式事件記錄發布為 OData 服務,客戶端可透過 LINQ 查詢。
LogEntry 對應事件記錄欄位,標記 [EntityPropertyMapping] 對應 Atom 標準元素 (Title、Summary、Updated)。LogDataSource 實作 IQueryable<LogEntry> LogEntries,使用 System.Diagnostics.EventLog 讀取 Application 記錄,支援依來源過濾、最新 200 筆。LogDataService : DataService<LogDataSource>,InitializeService 設定實體集存取權限、協定版本 (V2);CreateDataSource 從設定檔讀取來源名稱。[EntityPropertyMapping("Source", SyndicationItemProperty.Title, SyndicationTextContentKind.Plaintext, true)]
[EntityPropertyMapping("Message", SyndicationItemProperty.Summary, SyndicationTextContentKind.Plaintext, true)]
[EntityPropertyMapping("TimeGenerated", SyndicationItemProperty.Updated, SyndicationTextContentKind.Plaintext, true)]
[DataServiceKey("EventID")]
public class LogEntry {
public long EventID { get; set; }
public string Category { get; set; }
public string Message { get; set; }
public DateTime TimeGenerated { get; set; }
public string Source { get; set; }
}
public class LogDataSource {
private string _source;
public LogDataSource(string source) { _source = source; }
public IQueryable<LogEntry> LogEntries {
get { return GetEntries().AsQueryable().OrderBy(e => e.TimeGenerated); }
}
private IEnumerable<LogEntry> GetEntries() {
var appLog = EventLog.GetEventLogs().FirstOrDefault(e => e.Log == "Application");
var list = new List<LogEntry>();
if (appLog != null) {
foreach (EventLogEntry entry in appLog.Entries) {
if (_source == null || entry.Source.Equals(_source, StringComparison.OrdinalIgnoreCase)) {
list.Add(new LogEntry {
Category = entry.Category,
EventID = entry.InstanceId,
Message = entry.Message,
TimeGenerated = entry.TimeGenerated,
Source = entry.Source
});
}
}
}
return list.OrderByDescending(e => e.TimeGenerated).Take(200);
}
}
public class LogDataService : DataService<LogDataSource> {
public static void InitializeService(DataServiceConfiguration config) {
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
protected override LogDataSource CreateDataSource() {
string source = ConfigurationManager.AppSettings["EventLogSource"];
if (source == null) throw new ApplicationException("Missing EventLogSource appSetting");
return new LogDataSource(source);
}
}
var ctx = new LogDataService.LogDataSource(new Uri("https://localhost:3399/LogDataService.svc/"));
foreach (var item in ctx.LogEntries) {
Console.WriteLine($"來自 {item.Source} 事件 {item.EventID}, 內容 {item.Message}");
}