Hallo,
im Rahmen meiner Masterarbeit arbeite ich zur Zeit an einem Geräteserver. Der Server holt sich Werte von verschiedenen Geräten wie SPS, Leistungsmessgerät, Sensoren usw. die über verschiedene Arten und Schnittstellen angebunden sind. Zum Beispiel USB, CAN, Flexray, TCP/IP.
Zum Server gehört ein Clients der definiert welche Werte von welchen Geräten er haben möchte und teilt dies dem Server mit. Der Server startet und verwaltet die GEräte und stellt dem Client die Werte zur Verfügung. Entweder direkt (eingebunden als DLL in Client App) oder über TCP/IP.
Die Datenrate mit der die Werte aus den Geräte gelesen und übertragen werden soll liegt bei einigen bei 1 oder 5 m/s meist eher 10m/s , der Datentype sollte i.d.R. ein primitiver Typ sein.
Nun möchte ich in meiner Server-Applikation ein Datenlogging/DataHistory anlegen. Dazu habe ich eine sycronisierte Queue angelegt in die Wert, Zeitpunkt und Geräte(Herkunft/Id abgelegt werden können. Nun würde ich mir einen Task anlegen der diese Queue ausließt und alles was darin ist persistent abspeichert.
Meine Anforderung:
Meine bisherigen Ideen sind:
Nun bin ich mir unsicher was ich nutzen sollte. Vorallem was die Performance angeht. Um den Punkt Umgänglichkeit zum umschiffen hab ich auch schon überlegt die Funktion einbaue aus den gespeicherten Werten eine Excel-Datei zu genieren. Am meisten bin ich von SQLite angetan, aber mein Betreuer aus oben genannten Gründen nicht 😜
Habt ihr noch andere Ideen? Oder Argumente pro SQLite?
Viele Grüße
Hallo #CPferdchen,
wenn du eh am Server arbeitest, so kannst du dort eine richtige Datenbank verwenden. Z.B. SQL Server und dort die Daten hinschreiben.
Für die Verwaltung der Werte bzw. Umgänglichkeit erstellt du eine (einfache) Web-Anwendung und somit kann auch ein ungeschulter Benutzer die Daten manipulieren (entsprechende Rechte können vorausgesetzt werden in der Anwendung).
Über Reporting Services, usw. könnten dann auch gleich Diagramme, Berichte erstellt werden.
sycronisierte Queue angelegt in die Wert, Zeitpunkt und Geräte(Herkunft/Id abgelegt werden können. Nun würde ich mir einen Task anlegen der diese Queue ausließt und alles was darin ist persistent abspeichert.
Ob ein Task reicht od. nicht hängt von der Anwendung ab.
Alternativ kannst du auch einen Logging-Dienst erstellen und dein Programm kommuniziert mit diesem Dienst per WCF (ev. mit MessageQueue-Binding). Deine Anwendung stellt die Daten in diese "Qeueu" und der Dienst liest die Daten sicher aus und speichert diese in der Datenbank.
Ev. ist dies aber schon zuviel des Guten und ein Task reicht auch. Das musst du entscheiden.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Ich würde Dir an Deiner Stelle Event Tracing empfehlen.
Es ist etwas komplexer als normales Logging, dafür rasend schnell - so wird es in der CLR für die Garbage Collector Statistiken benutzt.
Ich habe selber etwas dazu auf meinem Blog - Windows Event Tracing in C# - vor kurzem geschrieben.
Edit: Mit Perfview kannst Du in Excel exportieren - wichtig ist auch, daß das Sammeln und das Auswerten getrennt sind. Es gibt auch andere Tools zum Sammeln, die zum Beispiel anhand der Dateigröße rollen. Es gibt viele Möglichkeiten, aber das ganze ist nicht so einfach.
Hallo,
Vielen Dank für eure Antworten.
wenn du eh am Server arbeitest, so kannst du dort eine richtige Datenbank verwenden. Z.B. SQL Server und dort die Daten hinschreiben.
Würde aber heißen, dass immer wenn ich ein neues System mit dem Geräteserver aufsetze ich auch einen SQL Server mit aufsetzen muss. Ein zentraler SQL Server in unserem Unternehmen wäre hier die Lösung, aber der Geräteserver soll auch isoliert vom Netz funktionieren.
Alternativ kannst du auch einen Logging-Dienst erstellen und dein Programm kommuniziert mit diesem Dienst
Das ganze als Dienst laufen zu lassen ist eine super Idee. Kannte ich als eigene Anwedung in C# bis her nicht. Wenn ich mir dieses Tutotial Windows Services mit C#so anschaue wäre das vielleicht auch was für meine TCP Client/Server Kommunikation.
Ob ein Task reicht od. nicht hängt von der Anwendung ab.
Wie meinst du das? Die Anzahl der Task oder ob ich einen Dienst verwende?
Ich würde Dir an Deiner Stelle Event Tracing empfehlen.
Es ist etwas komplexer als normales Logging, dafür rasend schnell - so wird es in der CLR für die Garbage Collector Statistiken benutzt.
Ich habe selber etwas dazu auf meinem Blog vor kurzem geschrieben.
Rasend schnell hört sich gut an 😄. Werde mal versuchen dazu eine Test Applikation zu schreiben. Hast du noch weitere nützliche Links zu dem Thema?
Ich habe gestern dieses mit SQLite gebastelt, aber euere Lösungen hören sich schneller und professioneller an.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Threading;
using System.Threading.Tasks;
using VB.Core.Channel;
//TODO: Erkennen und separieren der Channel auf einzelne Tables
//TODO: Eigene Spalten in den Tables statt einen String
//TODO: gescheiten Zeitstempel anlegen
namespace VB.Server
{
public class Data
{
public Data (ChannelAddress channelAddress, Type channelType, object value)
{
ChannelAddress = channelAddress;
ChannelType = channelType;
Value = value;
}
public ChannelAddress ChannelAddress { get; set; }
public Type ChannelType { get; set; }
public object Value { get; set; }
public override string ToString ()
{
return string.Format ("{0} | {1} | {2}", ChannelAddress, ChannelType, Value);
}
}
public static class DataHistory
{
public static Queue SynchronizedQueue = Queue.Synchronized (new Queue (new Queue<Data> ()));
private static readonly object _lockObject = new object ();
public static void syncEnqueue (ChannelAddress channelAddress, Type channelType, object value)
{
lock (_lockObject)
{
SynchronizedQueue.Enqueue (new Data (channelAddress, channelType, value));
}
}
public static string syncDequeue ()
{
lock (_lockObject)
{
return (SynchronizedQueue.Dequeue ()).ToString ();
}
}
}
public class DataHistoryTask
{
private bool _shouldStop;
private const int TransactionLimit = 100;
public void Start ()
{
new Task (
() =>
{
SQLiteConnection.CreateFile ("sqliteTest.db");
SQLiteConnection sqLiteConnection = new SQLiteConnection ();
sqLiteConnection.ConnectionString = "Data Source = sqliteTest.db; Version=3";
sqLiteConnection.Open ();
SQLiteCommand sqLiteCommand = new SQLiteCommand (sqLiteConnection);
sqLiteCommand.CommandText = "CREATE TABLE IF NOT EXISTS Test (tick INTEGER NOT NULL, str VARCHAR(200) NOT NULL)";
sqLiteCommand.ExecuteNonQuery ();
while (_shouldStop != true)
{
Thread.Sleep (1000);
if (DataHistory.SynchronizedQueue.Count < 1000)
{
continue;
}
using (var sqLiteTransaction = sqLiteConnection.BeginTransaction ())
{
sqLiteCommand.Connection = sqLiteConnection;
sqLiteCommand.Transaction = sqLiteTransaction;
int transactionCounter = 0;
while( DataHistory.SynchronizedQueue.Count > 0 && transactionCounter < TransactionLimit)
{
sqLiteCommand.CommandText = "INSERT INTO Test (tick, str) VALUES(1,'" + DataHistory.syncDequeue () + "')";
sqLiteCommand.ExecuteNonQuery ();
transactionCounter++;
}
sqLiteTransaction.Commit ();
Thread.Sleep (1);
}
}
sqLiteConnection.Close ();
}).Start ();
}
public void Stop ()
{
_shouldStop = true;
}
}
}
EDIT:
if (DataHistory.SynchronizedQueue.Count < 1000)
{
continue;
}
und
while( DataHistory.SynchronizedQueue.Count > 0 && transactionCounter < TransactionLimit)
muss ich nochmal abändern 😛
LG
Schau Dir die Channel 9 Videos und diese Übersicht an.
Ich habe noch mehr Material als Powerpoint.
Hallo #CPferdchen,
Wie meinst du das? Die Anzahl der Task oder ob ich einen Dienst verwende?
Ich meine das so, dass es darauf ankommt wie sehr du das Logging von der Anwendung entkoppeln willst. Mit dem separaten Dienst ist das Logging in einen eigenen Prozess - den Dienst-Prozess - ausgelagert mit allen Vor- und Nachteilen.
Wird mittels Task geloggt, so ist das Logging im selben Prozess. Wobei Logging duch Task wohl am ehesten per Producer/Consumer (siehe z.B. auch Sinnvoller Einsatz des Producer Consumer Patterns) umgesetzt wird.
Was für deine Anwendung und Anforderung besser passend ist, kann ich nicht beurteilen - das obliegt dir.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Hast du mal geschaut ob eine der Standard Logger, deiner Anforderungen erfüllen.
Log4Net, z.B. bietet die Möglichkeit in Dateien, Datenbanken oder als Mail zu loggen.
(Den Verwenden ich z.B. und falls doch mal was anderes Verlangt wird, habe ich einen Wrapper um den Logger und die Faktory geschrieben (grob 10 Zeilen Code))
Sollte man mal gelesen haben: