/// <summary> /// Lädt den XML Export der Datenbank in die Modelklasse. /// Vorgegebene Methode, hier ist nichts zu verändern. /// </summary> /// <param name="filename">Quelldatei</param> public void LoadXml(string filename) { XDocument doc; XElement root; try { doc = XDocument.Load(filename); root = doc.Root; } catch { return; } Tankstellen = (from t in root.Elements("Tankstelle") select new Tankstelle { Id = int.Parse(t.Attribute("Id").Value), Bundesland = t.Attribute("Bundesland").Value, PLZ = int.Parse(t.Attribute("PLZ").Value), Betreiber = t.Attribute("Betreiber").Value, Tagespreise = (from tp in t.Elements("Tagespreis") select new Tagespreis { Tankstelle = int.Parse(tp.Attribute("Tankstelle").Value), Tag = DateTime.ParseExact(tp.Attribute("Tag").Value, "yyyy-MM-dd", CultureInfo.InvariantCulture), PreisBenzin = decimal.Parse(tp.Attribute("PreisBenzin").Value, CultureInfo.InvariantCulture), PreisDiesel = decimal.Parse(tp.Attribute("PreisDiesel").Value, CultureInfo.InvariantCulture), Verkaeufe = (from v in tp.Elements("Verkauf") select new Verkauf { Id = int.Parse(v.Attribute("Id").Value), Tankstelle = int.Parse(v.Attribute("Tankstelle").Value), Tag = DateTime.ParseExact(v.Attribute("Tag").Value, "yyyy-MM-dd", CultureInfo.InvariantCulture), VerkaufBenzinLiter = v.Attribute("VerkaufBenzinLiter") == null ? (decimal?)null : decimal.Parse(v.Attribute("VerkaufBenzinLiter").Value, CultureInfo.InvariantCulture), VerkaufDieselLiter = v.Attribute("VerkaufDieselLiter") == null ? (decimal?)null : decimal.Parse(v.Attribute("VerkaufDieselLiter").Value, CultureInfo.InvariantCulture), VerkaufShopEuro = v.Attribute("VerkaufShopEuro") == null ? (decimal?)null : decimal.Parse(v.Attribute("VerkaufShopEuro").Value, CultureInfo.InvariantCulture), }).ToList() }).ToList() }).ToList(); // Referenzen auf alle Tagespreise und Verkäufe setzen. Tagespreise = Tankstellen.SelectMany(t => t.Tagespreise).ToList(); Verkaeufe = Tagespreise.SelectMany(tp => tp.Verkaeufe).ToList(); // Rücknavigationen schreiben. foreach (Tagespreis tp in Tagespreise) { tp._Tankstelle = Tankstellen.FirstOrDefault(t => t.Id == tp.Tankstelle); } foreach (Verkauf v in Verkaeufe) { v._Tagespreis = Tagespreise.FirstOrDefault(tp => tp.Tankstelle == v.Tankstelle && tp.Tag == v.Tag); } }
/// <summary> /// Die zu überschreibende Service-Methode /// </summary> /// <param name="request">Daten der Anfrage</param> /// <param name="responseStream">Der Stream, in den die Ausgabe erfolgen soll</param> /// <param name="context"></param> /// <returns>Fertigmeldung über Task-Objekt</returns> public override async Task Tankstellenpreise(TankstellenpreiseRequest request, IServerStreamWriter <Tankstellen> responseStream, ServerCallContext context) { // Awaitable anlegen, um die asynchrone Abarbeitung steuern zu können var taskCompletionSource = new TaskCompletionSource(); // max. Anzahl der zu übertragenden Datensätze int count = request.Anzahl; // Subscription auf das Observable der Tankstellenverwaltung using (tankstellenverwaltung.Tankstellen.Subscribe(async liste => { try { // Prüfen, ob der Stream abgebrochen werden soll context.CancellationToken.ThrowIfCancellationRequested(); // Von Protobuf generierte Datenklasse instanzieren und mit den erhaltenen Daten füllen var response = new Tankstellen(); response.Liste.AddRange(liste.Select(t => new Tankstelle { Name = t.Name, Super = t.Super, Diesel = t.Diesel })); // Daten über Stream senden await responseStream.WriteAsync(response); count--; if (count <= 0) { // Wenn Anzahl erreicht, kann die Methode kontrolliert beendet werden taskCompletionSource.SetResult(); } } catch (Exception ex) { logger.LogError(ex, "Abbruch Grpc-Stream"); // Kontrollierter Abbruch der Methode taskCompletionSource.SetResult(); } })) { // Auf die Fertigstellung der Aufgabe bzw. deren Abbruch warten await taskCompletionSource.Task; // Subscription wird mit Verlassen des Blocks beendet } }