Laden...
Avatar #avatar-2894.jpg
gfoidl myCSharp.de - Team
Entwickler in der Gasmotorenbranche (nicht nur Software) Waidring Dabei seit 07.06.2009 6.911 Beiträge
Benutzerbeschreibung
FIS-Speedski (S-DH) world champion 2015 3x FIS-Speedski (S-DH) overall worldcup winner, 2008/09, 2009/10, 2012/13 5x Subaru Velocity Challenge winner, 2009, 2010, 2013, 2014, 2015 7x PopKL Verbier winner, 2009 2x, 2010 2x, 2011 2x, 2013 1x 27 victories in 69 international Speedski-races v_max = 208,333 km/h http://de.wikipedia.org/wiki/Günther_Foidl

Forenbeiträge von gfoidl Ingesamt 6.911 Beiträge

04.08.2017 - 14:54 Uhr

Hallo MarsStein,

mit deiner Aussage, dass keine propriertären Features in die Sprache sollten, stimm ich dir zu.
Ich denke aber du hast den Vorschlag missverstanden, wie Abt auch geschrieben hat.

Beim aktuellen Vorschlag gefällt mir nur die Syntax nicht ganz, denn die passt nicht zu C#. Es muss ja nicht 1:1 den C/C++ Intrinsics gleichen. Es könnte eine schönere Variante gewählt werden.

Noch besser würde ich es finden, wenn System.Numerics.Vector<T> um dies erweitert werden würde. Dann kann in OOP ausgedrückt werden was ich will und der JITer übernimmt das wie es geht.
Außerdem könnte so bestehender Vector<T>-Code von diesem Vorschlag profitieren.
Gut es lassen sich nicht alle SSE*, AVX*, etc. mit Vector<T> abbilden, dafür könnten aber neue analoge Typen erstellt werden.

Edit: siehe nächste Antwort von mir.

Hallo Abt,

Performance spielt für die .NET Core Welt eine viel höhere Rolle als für das .NET Framework.

Das würde ich so nicht unterschreiben. Nur beim .net Framework war es eine "Friss od. Stirb" Alternative, bei .net Core ist es offen und "jeder" kann sich der Performance widmen, das in Teilen auch passiert. Beim .net Full hat sich MS oft leider nicht um die Performance gekümmert und oft wäre es relativ einfach gewesen das besser hinzubekommen, wie viele PRs in .net Core zeigen.

mfG Gü

04.08.2017 - 14:08 Uhr

Hallo Grimmbizkit,

klar gibt es Unterschiede, nur ob diese relevant / spürbar sind ist eine andere Sache 😉

Wenn das Intervall 250ms ist, so kann ich mir nicht vorstellen dass es mit HTTP irgendwelche Probleme geben sollte. V.a. wenn nur einfache Texte übertragen werden. Es gibt ja auch WebServer (HTTP) die mehrere Tausend Request pro Sekunden behandeln können, daher (ich wiederhole mich) sollte es kein Problem geben.

Ich würde es so einfach -- zumindest als Prototyp -- nachstellen und verifizieren ob es passt od. nicht. Falls ja, so ist es gut, sonst such dir eine Alternative. Aber gehe von "ja" aus.

mfG Gü

04.08.2017 - 13:49 Uhr

Hallo Grimmbizkit,

nimm besser einen HTTP-API (Web Api), damit kannst du alle geforderten Punkte leicht(er) umsetzen.
Noch dazu gewinnst du so mehr Freiheiten in der Wahl der Clients, das Debugging ist einfacher (HTTP-Traffic), usw.

Remoting läuft unter Mono afaik nicht -- aber das steht auf der Mono-Site.

mfG Gü

04.08.2017 - 13:45 Uhr

Hallo Abt,

Ein Pull Request ist ein Vorschlag.

So wie ich es sehe ist es keine Pull Request, sondern eine **Issue **mit dem Vorschlag.

Ein Pull Request wäre dann eine Codeänderung (in einem Feature-Branch) mit der Bitte um Review und Merge zu master 😉

Aber der Vorschlag ist sehr interessant!

mfG Gü

04.08.2017 - 09:39 Uhr

Hallo Taipi88,

lt. verlinktem Node-Modul ist es UDP.

mfG Gü

04.08.2017 - 09:32 Uhr

Hallo eclere,

das ist mehr od. weniger eine immanente Eigenschaft von relationalen Datenbanken.

Wenn du nicht an den SQL Server gebunden bist, so wäre hier ein Blick zu NoSQL-Vertretern (MongoDB, etc.) passend. Damit kann dieser Fall besser abgebildet werden.

Sonst lassen sich m:n-Beziehungen nur via einer "Verbindungstabelle" auflösen. Außer du verzichtest auf die Verknüpfung und legst die Daten einfach so ab, aber dann gibst du auch eine Eigenschaft, die referentielle Integrität, auf.

mfG Gü

04.08.2017 - 09:28 Uhr

Hallo bonobocoding,

portieren wird für dich wohl kaum jemand den Code -- da musst du selbst durch und bei konkreten Fragen kann dir das Forum gerne helfen.
Die Fragen, welche du unten in den Kommentaren zum Code-Schnippsel stellst, lassen sich auch via :rtfm: lösen.

Nur soviel: das '\xFF\xFF\xFF\xFFgetinfo xxx' sind Magic-Bytes, welche den Beginn des Requests markieren. In .net wäre das dann ein byte[] mit den entsprechenden Einträge. Dazu kannst du dir auch die Methode Encoding.GetBytes anschauen -- hier ASCII wie es im Code angegeben wurde.

Es gibt aber Alternativen um Node.js-Module in .net zu integrieren:*Microsoft.AspNetCore.NodeServices *tjanczuk/edge: Run .NET and Node.js code in-process on Windows, MacOS, and Linux

Vllt. bist du auf diesem Wege besser dran.

mfG Gü

01.08.2017 - 12:18 Uhr

Hallo MoMa91,

du kannst auch per z.B. jQuery die Inhalte austauschen.

Durchlaufen von Statistiken

Wie schauen denn die Statistiken aus bzw. wie liegen die vor? Dann kann konkretere geantwortet werden.

mfG Gü

30.07.2017 - 18:44 Uhr

Hallo Bradley,

und einem potentiellen Helfer fehlt der genauere Kontext wie dein Projekt / Solution ausschaut.

Tritt dieses Problem auch auf, wenn du ein neues Projekt erstellst?
Verweist dein Projekt auf andere Projekte (in der Solution)?

Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 5.

mfG Gü

29.07.2017 - 17:23 Uhr

Hallo mfe,

appveyor schaut sich also die Solution an* und findet dann als erstes Projekt (nach alphabetischer Sortierung im Dateisystem) https://github.com/mfe-/Prism.Validation/blob/master/Core/Prism.Validation.Test/Prism.Validation.Test.UWP/Prism.Validation.Test.UWP.csproj mit


<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

Daher wird auch die MsBuild-Version so festgelegt.

Gib in appveyor.yml das Projekt direkt an. Od. gleich dotnet build ... dann bist du auf der sicheren Seite. dotnet build verwendet dann das korrekte MsBuild intern.

* zur Erklärung:

Zitat von: Build phase | AppVeyor
If project or solution file is not specified on project settings AppVeyor searches for the first occurence of *.sln or *.*proj file in the build clone directory recursively.

mfG Gü

29.07.2017 - 16:16 Uhr

Hallo mfe,

kannst du die appveyor.yml und die csproj-Datei zeigen?

Oder als Hilfe zur Selbsthilfe: nimm ein neues .net-Standard Projekt her und lass das mit der appveyor.yml laufen um so zu schauen ob der Fehler im csproj liegt od. in appveyor.

An und für sich kann appveyor schon mit .net Core / .net Standard Projekten umgehen.

mfG Gü

28.07.2017 - 15:47 Uhr

Hallo camelord,

abstrahiere das Ganze durch eine Schnittstelle (hier interface) weg und erstell einen Mock, der den Joystick -- od. generell den Input -- simuliert.

Leider kann ich jetzt nicht mehr schreiben, da ich weg muss, aber ich hoffe als Stichworte wirst du so fündig.

mfG Gü

28.07.2017 - 09:25 Uhr

Hallo Gimmick,

wo hast du das geändert? Oben schaut es gleich aus.

einer Bibliothek und scheinbar mag das keine parallele Ausführung

Da sollte auch in der Doku der Bibliothek stehen. Du kannst aber dennoch "parallel" arbeiten, wenn du die oben erwähnten Pipelines verwendest, denn dort wird (bzw. kann) jeder Schritt nur einmal gleichzeitig ausgeführt werden, dafür aber mehrere Schritte wie Laden, Sobel, etc. zur gleichen Zeit.

Parallel.ForEach ist oft die scheinbar einfachste Möglichkeit der Beschleunigung des Programmablaufs, meist ist es aber nicht die passendste und es gibt bessere Alternativen.

mfG Gü

27.07.2017 - 19:22 Uhr

Hallo Gimmick,

bzw nach was könnte ich da schauen?

Hierher :rtfm: Sonst ist das so auf die Schnelle nicht zielführend. Schau dir lieber gleich an wie es "richtig" geht und bau keine Hack-Lösung die von Problem zu Problem surft.

Das ist Code-Snippet beachtet außerdem [FAQ] Warum blockiert mein GUI? nicht.

mfG Gü

27.07.2017 - 17:44 Uhr

Hallo Gimmick,

Mir ist aber der Unterschied zwischen Tasks und Threads nicht klar.

Thread (Informatik) sagt da so ziemlich viel.

Ein Task (eingeführt mit .net 4.0) ist eine "Aufgabe" die dem Task-Scheduler übergeben wird. Dieser kümmert sich dann darum, dass der Task ausgeführt wird. Die Ausführung kann -- muss aber nicht, obwohl i.d.R. wird es so sein -- in einem Thread (genauer ThreadPool-Thread) erfolgen.

D.h. ein Task ist grob eine Abstraktion von Threads und das Arbeiten (hier programmieren) mit Tasks ist einfacher als mit Threads.

Bzgl. deiner Aufgabenstellung könnte auch Pipelines interessant sein. Wobei ich dir gleich auch empfehle das ganze eBook durchzugehen, dann hast du einen guten Einstieg in Tasks 😃

mfG Gü

27.07.2017 - 09:12 Uhr

Hallo HeikoAdams,

.net 4.6.2 ist ein Update von .net 4.5. Daher lässt es sich auch starten.

Nur die Reference-Assemblies sind andere, damit in Visual Studio beim Build die jeweils passenden Typen und Member vorhanden sind.

Wenn also Typen / Member verwendet werden, die mit .net 4.6.2 hinzugekommen sind, so kann das unter .net 4.5 nicht gut gehen, da diese dort eben niicht bekannt sind.
Einem Start der Anwendung steht aber nichts im Wege, da die CLR-Header gleich sind.

Probier einmal in VS das Target-Framework auf .net 4.5 umzustellen und schau ob dann der Build funktioniert. So siehst du was die Ursache für die Fehler unter .net 4.5 sein wird.

Aber die Lösung wäre einfach ein Update auf .net 4.6.2 😉

hat ihn jedoch mit diversen Fehlermeldungen bombadiert.

Welche? Sonst ist raten angesagt. Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 5.

mfG Gü

26.07.2017 - 17:42 Uhr

Hallo robin_, willkommen im Forum,

das geht dann (relativ einfach) per Datenbindung. Schau dir dieses Thema in WPF einmal an, da siehst du worauf das hinausläuft. Auch Das Model-View-ViewModel (MVVM) Entwurfsmuster für WPF ist empfehlenswert dafür.

mfG Gü

26.07.2017 - 09:10 Uhr

Hallo emuuu,

kennst du WCF-Tracing? Wenn nicht schau dir das einmal ein, denn da schreibt der Service-Stack selbst seine Fehler (entsprechende Konfiguration vorausgesetzt) und dort steht eine Menge drin, v.a. wenn der Trace-Level weit unten (z.B. ActivityTracing) ist. So solltest du den ursprünglichen Fehler ermitteln können.

BTW: für den "Broadcast" würde ich auch das Bordmittel nutzen -> UDP-Broadcast, anstatt das selbst zu implementieren. Dadurch kannst du den Fehler schon von vornherein vermeiden.
Od. -- je nach Art der Clients -- auch SignalR nutzen und dort gleich den neuen Datensatz mitübergeben, denn das spart einen Roundtrip zum Server.

mfG Gü

25.07.2017 - 16:55 Uhr

Hallo ErfinderDesRades,

während der Ausführung ist alles unter der höchsten 4.x Version die installiert wurde.

Während des Build-Vorgangs werden andere Reference-Assemblies (je nach FW-Version) verwendet, damit z.B. ein Projekt mit .net 4.0 nicht auf Member zugreifen kann, die in späteren Versionen erschienen sind.

Anders würde es sich verhalten, wenn .net 2.0 / 3.5 mit dem 4.x FW verwendet werden, da dort unterschiedliche CLR-Versionen vorhanden sind (side by side execution).

mfG Gü

21.07.2017 - 10:10 Uhr

Hallo pinki,

Fody steht unter der MIT-Lizenz und darin steht

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

Für Fody gilt dann "substantial portions of the Software".

Ich würde in der Info/About-Seite deiner Anwendung die Komponenten auflisten und die Lizenzen-Verlinken (sofern möglich, z.B. durch Link auf das Github-Projekt), sonst direkt anzeigbar machen.
So ähnlich hab ich das auch schon öfters gesehen. Schau dir dazu ein paar OpenSource-Projekte an, v.a. jene von GNU denn dann bist du ziemlich auf der sicheren Seite.

mfG Gü

19.07.2017 - 20:20 Uhr

Hallo Christoph K.,

hab deinen Edit nicht bemerkt, erst durch die Folgeantworten.

In wie fern bietet ein Baum Vorteile gegenüber einer binären Suche?

Naja, hast du dich mit Bäumen ein wenig auseinandergesetzt? Dann ergibt sich die Antwort dazu von selbst.

Es lassen sich Operationen wie Filtern besser abbilden bzw. lassen sich die Treffer einfacher ermitteln. Außerdem ist es möglich mehrere "Indexe" anzulegen.
Aber schau dir zuerst die Theorie dazu an und entscheide selbst.

Oder du lässt dich einfach empirisch überzeugen: SQL Server verwendet einen B*-Baum (wenn ich mich nicht täusche) für die Indexe. Wäre eine binäre Suche besser bzw. passender, so würde das wohl so umgesetzt worden sein.

PS: das mit der binären Suche hast du schon so richtig wiedergegeben. Der Aufwand davon ist O(log n).

mfG Gü

19.07.2017 - 14:58 Uhr

Hallo Christoph K.,

dass sie mir die Performance-Vorteile bringt?

Hast du dazu auch in der :rtfm: nachgeschaut? Dort steht (wenn ich mich recht erinnere) klar drinnen, dass es kein Allheilmittel ist -- und indirekt dass es für deinen Fall eh nicht geeignet ist. Doku lesen lohnt sich 😉

Gäbe es den eine Möglichkeit, die Daten schon vor dem speichern in Listen zu teilen.
Und zwar so, dass du deine Daten schon aufgeteilt in die Wertebereiche hast?

Und daher auch mein Vorschlag zu Baum-Strukturen in der vorigen Antwort. So kannst du den/die Index/e abbilden und die Zugriffe sind dann nahezu trivial.
Jedes andere Vorgehen ist "Murks" und bildet nur umständlich eine gute Datenstruktur nach. Es ist nicht nur aus Lust und Laune so, dass "alle" Datenbanken Baum-Strukturen für den Index verwenden (bei alle bitte die " nicht übersehen).

Da es aber viele Bäume gibt, musst du selbst einen passenden für deine Problemstellung finden. Es hängt u.a. auch davon ab ob mehr gelesen wie geschrieben wird, usw.

mfG Gü

19.07.2017 - 13:01 Uhr

Hallo Christoph K.,

Den Index-Zugriff kann ich in c# auch nachbauen,

Geht, aber mit passenden Baum-Strukturen.

Generell ist der Datentyp einer der wichtigsten Faktoren für gute Leistung, da so die Aufwandsklasse gesenkt werden kann.

im Framework schon irgendetwas vorgefertigtest gibt, sozusagen eine Indizierte Liste, oder etwas ähnliches?

In System.Collections.Generic stecken schon ein paar Klassen drin, wie SortedList<T>, SortedDictionary<K,V>, usw. Betrachte aber immer auch die Aufwandsklasse für die Operationen, welche du zu verwenden versuchst. O(1) ist besser als O(log n) und das ist besser als O(n) od. O(n²).

mfG Gü

18.07.2017 - 12:16 Uhr

Hallo susisorglos,

ad 1: Visual Studio 2017 Release Notes

ad 2: geht sicher irgendwie 😉 ggf. deinstallieren und die passende Version + Updates wieder installieren

mfG Gü

17.07.2017 - 15:19 Uhr

Hallo,

ah, das ist Linq2Sql. Schau dir mal den generierten Code an und dort v.a. die Eigenschaften. Wenn der gleiche Wert zugewiesen wird, macht er dort nichts, daher zeigt es auch keine Änderung, da daraus auch kein UPDATE abgesetzt werden soll.

mfG Gü

PS: Vorhin hab ich aus versehen den Inhalt der Zwischenablage reinkopiert. Da hat mir der Ghosttyper zuviel gemacht. Sorry.

15.07.2017 - 22:49 Uhr

Hallo micha0827,

eine genau Antwort kann ich dir leider nicht liefern, dazu fehlt mir das Wissen über deine Tabellen / Objekte.

Aber im oberen Snippet führt das Gruppieren Linq durch und im unteren der SQL Server.

Linq verwendet zum Gruppieren GetHashCode (bzw. IEqualityComparer<T>), hier der eines anonymen Typen.
SQL Server macht es grundsätzlich ähnlich, wie genau weiß ich nicht.
Aber da werden sich wohl beide Unterscheiden und deshalb sind die Ergebnisse anders.

Anstatt des anonymen Typen kannst du eine benannten Typen verwenden und dort entweder IEquality<T> implementieren od. bei GroupBy (als Erweiterungsmethode) eine Instanz von IEqualityComparer<T> angeben.

Sollte aber das Ergebnis mit Gruppierung in der DB das korrekte sein, so kannst du auch dieses verwenden.

BTW: das Skip(0) kannst du weglassen. Genauso das orderby vor dem Gruppieren, denn beim Gruppieren wird die Reihenfolge ohnehin über den Haufen geschmissen.

mfG Gü

15.07.2017 - 17:12 Uhr

Hallo -Rockbiest-,

entweder der Admin erlaubt ein Loch in der Firewall, so dass du* ein Netzlaufwerk einbinden kannst und so per \FileServer... zugreifen kannst. Nötige Ports musst du raussuchen

  • auf dem FileServer eine Web-Anwendung, die nur für für das "Streamen" der Dateien zuständig, laufen lässt und auf diesen dann z.B. per UrlRewrite (od. sonst eine reverse proxy Funktionalität) weiterleitest, dann ist nur TCP 80 freizugeben

  • du dir sonst einen Dienst für das Holen der Dateien schreibst, z.B. per WCF / TcpServer/Client / ... dann weißt du auch welche Ports freigegeben werden müssen

Der Aufwand steigt mit den unteren Punkten. Aber klär das mit dem Admin ab, der weiß ja was er zulassen kann und will.

Sonst wäre eine Erklärung hilfreich wie die Server-Architektur ausschaut, welche Betriebssysteme im Einsatz sind, etc. ganz hilfreich. Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 5.

mfG Gü

15.07.2017 - 15:55 Uhr

Hallo HeikoAdams,

Okay, jetzt hab ich es.

Hm, dann wundert mich warum die immer noch mit 0 herumkämpfst.

Vllt macht es das Beispiel klarer:


using System.Diagnostics;
using System.Linq;

namespace ConsoleApp1
{
	class Program
	{
		static void Main(string[] args)
		{
			using (DataClasses1DataContext db = new DataClasses1DataContext())
			{
				var kunde = db.Kunden.FirstOrDefault();

				int updateCount = db.GetChangeSet().Updates.Count;
				Debug.Assert(updateCount == 0);

				kunde.Name = "Neuer Name";			// diese Instanz von Kunde wird vom Context verfolgt

				updateCount = db.GetChangeSet().Updates.Count;
				Debug.Assert(updateCount > 0);
			}

			using (DataClasses1DataContext db = new DataClasses1DataContext())
			{
				var kunde = db.Kunden.FirstOrDefault();

				int updateCount = db.GetChangeSet().Updates.Count;
				Debug.Assert(updateCount == 0);

				kunde = new Kunde();               // diese Intanz ist dem Context unbekannt!
				kunde.Name = "Neuer Name";

				updateCount = db.GetChangeSet().Updates.Count;
				Debug.Assert(updateCount == 0);     // da es eben dem Context unbekannt ist, kann er die Änderung nicht verfolgen
			}
		}
	}
}

[Tutorial] Vertrackte Fehler durch Vergleich von echtem Projekt mit minimalem Testprojekt finden kann dabei auch helfen.

gibt ein InsertOnSubmit Pendant für Updates, das ich vergessen habe?

Bei Insert wäre es die Inserts-Eigenschaft von ChangeSet. Cf. ChangeSet Class | Microsoft Docs

mfG Gü

14.07.2017 - 23:01 Uhr

Hallo,

mach es gleich ordentlich mit einer wiederverwendbaren Erweiterungsmethode für TaskFactory. Trenne außerdem das Downloaden und das Deserialisieren, das sind zwei unterschiedliche Dinge.

Weiters ist es oft ratsam vor einem Retry eine kurze Zeit zu warten.


using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace ConsoleApp1
{
	public static class TaskFactoryExtensions
	{
		public static async Task<T> RetryOnFaultAsync<T>(this TaskFactory factory, Func<Task<T>> function, int maxTries, Func<Task> retryWhen = null)
		{
			if (factory == null) throw new ArgumentNullException(nameof(factory));
			if (function == null) throw new ArgumentNullException(nameof(function));
			if (maxTries < 1) throw new ArgumentOutOfRangeException(nameof(maxTries));

			for (int i = 0; i < maxTries; ++i)
			{
				try
				{
					return await function().ConfigureAwait(false);
				}
				catch
				{
					if (i == maxTries - 1) throw;
				}

				if (retryWhen != null) await retryWhen().ConfigureAwait(false);
			}

			return default(T);
		}
	}

	class Program
	{
		static void Main(string[] args)
		{
			Run().GetAwaiter().GetResult();
		}

		private static async Task Run()
		{
			var myService = new MyService();
			string url = "mir fällt nichts ein";

			string content = await Task.Factory.RetryOnFaultAsync(() => myService.DownloadAsync(url), 3).ConfigureAwait(false);

			// Oder mit kurzem Warten bevor der nächste Versuch gestartet wird:
			string content1 = await Task.Factory.RetryOnFaultAsync(() => myService.DownloadAsync(url), 3, () => Task.Delay(500));

			Foo foo = await myService.Deserialize<Foo>(content).ConfigureAwait(false);
		}
	}

	public class Foo { }

	public class MyService
	{
		private readonly HttpClient _httpClient = new HttpClient();

		public async Task<string> DownloadAsync(string url)
		{
			return await _httpClient.GetStringAsync(url).ConfigureAwait(false);
		}

		public async Task<T> Deserialize<T>(string content) where T : class
		{
			throw new NotImplementedException();
		}
	}
}

BTW: beim HttpClient wäre es besser diesen nur einmal zu instanziieren und dann immer die gleiche Instanz zu verwenden. Der hat ein wenig ein besonderes Verhalten. Dass er IDisposable implementiert ist hier trügerisch.

mfG Gü

14.07.2017 - 22:41 Uhr

Hallo HeikoAdams,

ziel wird ja auch in der 2. Zeile gefüllt und anschließend auf NULL geprüft. Deshalb wird es im Else-Zweig nicht verwendet 😉

😉 soweit konnte ich dem Code schon folgen.

Ja aber wo erwartest du eine Aktualisierung von ziel welche der DataContext mitbekommen soll?

Im if-Zweig wird der ziel-Variablen eine neues Objekt zugewiesen und das kennt der DataContext nicht, wie auch. Er kennt nur das Objekt, auf das vorher die ziel-Variable verwiesen hat.

Im else-Zweig passiert gar nichts mit ziel.

Wenn du im if-Zweig eine Eigenschaft von ziel änderst (und kein neues Objekt ziel zuweist), so wird auch eine Änderung angezeigt.

Klar?

Mit Modell meine ich den Datenkontext, aber das ist jetzt nicht mehr nötig.

mfG Gü

14.07.2017 - 13:53 Uhr

Hallo HeikoAdams,

kannst du bitte noch beschreiben die dein Modell aussieht? Ich sehe nichts od. übersehe ich es. Im else-Zweig wird nicht auf ziel zugegriffen, das verwirrt mich deshalb.

Du kannst im Modell auch einen Breakpoint beim Getter/Setter der Eigenschaften setzen um zu schauen ob die Werte überhaupt geändert werden.

mfG Gü

14.07.2017 - 13:48 Uhr

Hallo deisi,

oder aktivieren Sie die Ablaufverfolgung

Das wäre die passendere Option, da du so mehr über die Fehler in der Trace-Datei erfahren kannst.

Da du den Server -- lt. Code oben -- selbst hostet, so kannst du den auch mit dem Debugger laufen lassen und so noch einfacher die Ursache für den Fehler finden.

mfG Gü

14.07.2017 - 13:31 Uhr

Hallo inflames2k,

gut dass du die Lösung gefunden hast 😉
Fürs Debuggen ist es hier oft hilfreich einen Breakpoint in der Methode zu setzen, welchen das Event feuert (die OnXYZ-Methoden).

Da das Downgrade wohl "lange" (mehr als 1 Sekunde) dauern wird, würde ich einen extra Thread verwenden, anstatt einem aus dem ThreadPool. Und diesen Thread zur Sicherheit noch als Vordergrundthread einstellen, damit die AppDomain erst entladen wird wenn auch dieser Thread fertig ist.

Aber das hat mit dem eigentlichen Thema eh schon weniger zu tun.

mfG Gü

14.07.2017 - 13:22 Uhr

Hallo DeSchneller,

das Problem liegt sicher darin, dass WCF nicht weiß bzw. nicht wissen kann wie die Report-Komponente zu serialisieren ist.
Lass den Server einmal mit dem Debugger laufen od. logge die Fehler (fürs WCF-Logging schau :rtfm: ) um dies zu bestätigen.

Lässt sich die Report-Komponente überhaupt irgendwie serialiseren für den Anwendungsfall wie du ihn hast. Also kann diese Komponente binär, xml, json od. sonst irgendwie serialisiert werden?
Wenn das schon nicht geht, so geht es mit WCF auch nicht.
Ginge das, so kannst du WCF beibringen einen eigenen Serialisierer dafür zu verwenden.

Ist es grundsätzlich auch möglich dass der Client nur den fertig gerenderten Report in Form von HTML, Pdf, etc. bekommt?

Hier möchte ich die Reports vom Server generieren lassen

Warum das eigentlich? Od. kannst du dem Client die nötigen Daten liefern und der rendert dann bei ihm?
Ich kenn dein System und die Software nicht, aber ich würde das eher am Client rendern lassen.

mfG Gü

13.07.2017 - 13:33 Uhr

Hallo Christoph K.,

dann kommst du einen Header, der den Inhalt der Datei beschreibt, nicht umher.
In diesem Header kann dann z.B. stehen von wo bis wo od. von wo und welche Länge welche Daten stehen.

mfG Gü

13.07.2017 - 12:24 Uhr

Hallo deisi,

SecurityNegotiationException

Hast du da in Verbindung mit TCP-Binding mal gegoogelt?

Gib bei der Binding den entsprechenden SecurityMode an und dann klappt es (z.B. None).

Dass die Firewall hier nichts block hast du ja getestet und außerdem wäre dann die Fehlermeldung anders.

mfG Gü

13.07.2017 - 12:21 Uhr

Hallo Christoph K.,

das mit der Länge -- wie von Th69 vorgeschlagen -- ist sicherlich die beste Lösung. Wird bei HTTP mit der ContentLength und bei anderen Protokollen auch erfolgreich eingesetzt.

Als weitere Alternative könntest du "Magic bytes" verwenden. Also eine Folge von Bytes, die sonst mit sehr hoher Wahrscheinlichkeit nicht vorkommen werden, und anhand dieser separieren.
Dabei muss beim Lesen allerdings jedes Byte geprüft werden. Bei der Variante mit der Länge kann der ganze "Block" auf einmal gelesen werden und das ist schon einfacher 😉

mfG Gü

13.07.2017 - 10:26 Uhr

Hallo Kampfwurst,

dafür ein eigenen Service zu verwenden erscheint mir als Overkill. Der tut ja nichts, außer zu warten und dann -- wenn die Zeit gekommen ist -- die "Funktion" starten. Außerdem muss so die nächste Ausführung (irgendwo) gespeichert werden.

In Windows gibt es "geplante Aufgaben" / "scheduled tasks" und diese würde ich dafür verwenden. Da übernimmt das Betriebssystem das Speichern des Zeitplans, die Ausführung, usw.

Mit Schtasks kannst du die Aufgabe erstellen. Erstell die erste Aufgabe manuelle, also da wählst du den Zeitpunkt. Als Aktion wird dabei ein (Batch-) Script aufgerufen, welches folgende Schritte hat:1. die Funktion aufrufen

  1. den nächsten Zeitpunkt ermitteln (Zufallszahlen können per %random% ermittelt werden

Wenn dir Batch nicht taugt, kannst du dafür auch PowerShell od. ein simples C#-Programm verwenden (Process-Klasse ruft dann schtasks und womöglich auch deine Funktion auf)

mfG Gü

12.07.2017 - 19:50 Uhr

Hallo Kampfwurst,

wo läuft die "Funktion"? In deinem Programm, in der Cloud, etc. Od. ist deine Funktion eine EXE die zu diesen Zeiten aufgerufen werden soll?

Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 5.

Die Tage sind auch zufällig zu wählen.

Wie ist das zu vertehen? So dass an jedem Tag (vom "Timer") zu entscheiden ist ob die Funktion heute zu den zufälligen Zeiten laufen soll od. nicht od. sollen z.B. 4 Tage der Woche zufällig gewählt werden.

mfG Gü

08.07.2017 - 14:08 Uhr

Hallo Christoph K.,

es spielen ja noch mehr Fragen mit:* von welcher Art sind die IDs? int, Guid, etc.

  • soll diese Datenbank nur für diese Daten verwendet werden od. auch andere Daten liefern?
  • du schreibst von einem Server, der erweitert werden kann. Können es auch mehr Server sein?
  • geht es (auch in Zukunft) rein nur ums Lesen/Schreiben der Key/Values?

Einen Url-Hash würde ich auch nicht verwenden. Du spart ev. etwas vom Speicherplatz, dafür brauchst du mehr CPU fürs Hashen.

Wenn die Datenbank nur für diesen Zweck ist, so halte ich es "übertrieben" eine allgemeine SQL Datenbank für Key-Value zu verwenden. Da gibt es spezialisiertere Varianten, die für diese Aufgaben passender sind. Redis wäre so ein klassischer Vertreter, allerdings wurde afaik das "virtual memory"-Projekt davon eingestellt. Aber es gibt dafür ja sonst genug Alternativen.

Sollten mehrere Server im Einsatz sein können, so kannst du v.a. die Disk-Operationen aufteilen und so (oft) viel an Performanz gewinnen (vorausgesetzt natürlich dass die Daten korrekt auf die Server verteilt wurden ~ Sharding).

128MB DDR4

Kein Wunder dass der Index nicht im RAM Platz hat 😉

mfG Gü

08.07.2017 - 11:57 Uhr

Hallo Christoph K.,

erzähl uns noch ein wenig über die Infrastruktur-Bedingungen, dann lässt sich eine bessere Empfehlung abgeben.

On Premise od. Cloud?

Bei On Premise wie viele Server können verwendet werden (wegen Sharding, etc.)?

MySQL sowie die anderen "klassischen" SQL-DBMS würde ich für solche Aufgabe sowieso ausschließen und einen passenden Vertreter der NoSQL-Welt nehmen. Die sind aber sehr oft auf die Infrastruktur angepasst, daher ist dieses Detail wichtig zu wissen.

mfG Gü

07.07.2017 - 18:26 Uhr

Hallo Palladin007,

du hast vermutlich C# 7 New Features: Non-Nullable references, Local Functions, Immutable Objects gemeint.

In Proposal for C# Non-Nullable Reference Types gibt es einen offiziellen Vorschlag dazu.

Schauen wir einmal ob (bin mir ziemlich sicher dass das kommt) und wie genau das eingeführt wird.

mfG Gü

02.07.2017 - 22:34 Uhr

Hallo oehrle,

muss da etwas bestimmtes beachtet werden?

Schau z.B. Where do I put my data to keep it safe from ClickOnce updates?, da steht das wie ich es meinte in/mit AppData.

diese so wie die Config.exe behandeln könnte. Allerdings arbeite ich immer nur mit einer "NameValueCollection"

Lass die app.config einfach als Config für die App so stehen und pack "deine" Konfiguration, die wie du schreibst Name-Values sind in eine xml, json, etc. Datei. Mit einer simplen Hilfsklasse die per Indexer (key = Name) auf Values zugreifst hast du eine einfache und saubere Lösung.

Da ist das herumhacken in app.config schwierigern, fehleranfälliger, etc.

mfG Gü

02.07.2017 - 17:13 Uhr

Hallo oehrle,

Hat jemand eine Idee an was das lieen könnte?

Konkret nicht, außer vllt. an eine Besonderheit (einem Feature) von ClickOnce.

Schreib die zu ändernden Einstellungen besser in eine separate Datei und pack diese in AppData. Also getrennt von app.config, da du so mehr Kontrolle hast.

mfG Gü

30.06.2017 - 11:38 Uhr

Hallo herbivore,

amüsant und doch sehr treffend den Nagel in ... äh... auf den Punkt gebracht 😃

V.a. den Schluss sollte wirklich jeder beherzigen, der mit dem Thema (Big-) Data zu tun hat.
Kausalität und Korrelation korrelieren nicht immer.

mfG Gü

30.06.2017 - 11:30 Uhr

Hallo MoMa91,

somit kann man dann über die AD-Gruppen-Namen die Rollen bestimmen, die Zugriff haben?

ja.

also verwende ich .NET Full wenn ich das richtig gegoogelt habe.

Naja, das hat du beim Anlegen des Projektes gewählt. Weil in der Registry ein passender Key ist heißt das ja nur dass .net Full installiert ist.

mfG Gü

30.06.2017 - 08:27 Uhr

Hallo MoMa91,

es geht aus den Links indirekt hervor, aber welche welches Asp.net verwendest du? Basierend auf .net Core od. .net Full?

Danach unterscheidet sich auch (teilweise) die weitere Vorgehensweise.

Windows-Authentifierung lässt sich unter .net Full und .net Core bewerkstelligen.
Stell einfach einmal auf Windows-Authentication und schau was passiert.
Bei .net Core geht das allerdings nur beim IIS-Hosting, sonst muss das selbst bzw. durch andere Komponenten bewerkstelligt werden.

Jedoch musste ich nirgends eine Domäne angeben, bzw. Servername. Dadurch funktioniert die Authentifizierung mit jedem beliebigen Benutzer innerhalb des Netzes.

Servername kommt von der Domäne zu welcher der Webserver beigetreten ist.
Domäne gibt der der User doch bei der Anmeldung mit an (wenn auch implizit wie im IE).

BTW: hast du auf dem von dir verlinkten Blog den Folgebeitrag gar nicht gesehen? Active Directory Authentication with OWIN in MVC5. Part 2: Roles and Corrections

mfG Gü

29.06.2017 - 14:40 Uhr

Hallo Palin,

du übersiehst nichts.

p = f(T, A, B, C, D, E, F) und anhand der Tabelle lassen sich Paare (p,T) bilden. Somit ist es ein (lineares) Gleichungssystem (zumindest nach minimaler Umformung).

Kältemittels R134a

Dazu findet sich nichts? Es gibt auch noch andere Gleichungen und mich würde es wundern, falls es dazu keine Parameter gibt, da dieses Kältemittel doch recht häufig verwendet wird.

mfG Gü

29.06.2017 - 14:29 Uhr

Hallo lhyn,

das lässt sich besser abbilden. Guck mal, so in etwa würde ich das machen.


class Program
{
    static void Main()
    {
        var dampfTafel = new DampfTafel(DampfTafelQuelle.LeseNachTempSortierteWerte());

        DampfPunkt werteFür2C = dampfTafel.GetDampfDruck(2);
    }
}

[DebuggerDisplay("{" + nameof(TempInC) + "} °C | {" + nameof(DruckInBar) + "} bar")]
public struct DampfPunkt
{
    public double TempInC { get; }
    public double DruckInBar { get; }

    public DampfPunkt(double tempInC, double druckInBar)
    {
        this.TempInC = tempInC;
        this.DruckInBar = druckInBar;
    }
}

public static class DampfTafelQuelle
{
    public static IEnumerable<DampfPunkt> LeseNachTempSortierteWerte()
    {
        yield return new DampfPunkt(-50, 0.299);
        yield return new DampfPunkt(-45, 0.396);
        // usw.
        // od. Lesen aus einer Datei, Datenbank, wie auch immer es zur Verfügung steht
        yield return new DampfPunkt(0, 2.929);
        yield return new DampfPunkt(5, 3.497);
        yield return new DampfPunkt(10, 4.146);
    }
}

public class DampfTafel
{
    private readonly DampfPunkt[] _dampfPunkte;

    public DampfTafel(IEnumerable<DampfPunkt> dampfPunkte)
    {
        _dampfPunkte = dampfPunkte?.ToArray() ?? throw new ArgumentNullException(nameof(dampfPunkte));
    }

    public DampfPunkt GetDampfDruck(double tempInC)
    {
        int idx = Array.BinarySearch(_dampfPunkte, new DampfPunkt(tempInC, double.NaN), new DampfPunktTempComparer());

        if (idx > 0) return _dampfPunkte[idx];

        idx = ~idx;
        DampfPunkt p0 = _dampfPunkte[idx - 1];
        DampfPunkt p1 = _dampfPunkte[idx];

        // lineare Interpolation
        double druck = p0.DruckInBar + (p1.DruckInBar - p0.DruckInBar) / (p1.TempInC - p0.TempInC) * (tempInC - p0.TempInC);

        return new DampfPunkt(tempInC, druck);
    }

    private class DampfPunktTempComparer : Comparer<DampfPunkt>
    {
        public override int Compare(DampfPunkt x, DampfPunkt y) => x.TempInC.CompareTo(y.TempInC);
    }
}

Index-Prüfungen, etc. kannst du selbst einbauen.

genau diese erweiterten Parameter {D, E, F} kann ich nicht finden, ist definitiv die eleganteste Lösung

Ist die "einfache" bzw. klassische Antoine-Gleichung zu ungenau?
Bedenke dass auch durch Interpolation Fehler entstehen, daher ist es dann abzuwägen welche Methode genauer ist.
Vergleich das einmal und überlege inwiefern die Genauigkeit für die Endanwendung eine Rolle spielt.
Da der Verlauf sich logarithmisch als Gerade abbilden lässt, könntest du für die Interpolation die Werte logarithmisch speichern, dann als Gerade interpretieren und so genauer interpolieren, anschließend wieder zurückrechnen. Aber ich vermute dass dies seitens Berechnung zu genau für den praktischen Anwendungsfall sein wird.

mfG Gü

29.06.2017 - 11:44 Uhr

Hallo lhyn,

wie ich die Parameter aus den Dampftabellen bekomme...

Was verstehst du unter "Dampftabelle" bzw. welche hast du?

In der Antoine-Gleichung sind die Parameter {A, B, C} bzw. in der erweiterten Form {A, B, C, D, E, F} empirisch ermittelt und daher gibt es dazu auch eigenen Tabellen. Zur Online-Abfrage kannst du z.B. die Dortmunder Datenbank anzapfen -> Saturated Vapor Pressure.

Zur Frage der Interpolation müssen wir zuerst den Aufbau deiner verwendeten Dampftabelle kennen.
Aber grundsätzlich baue eine geordnete Liste mit Wertpaaren (T, Sattdampdruck). Suche dann auf Basis von T das Wertpaar, das die Zieltemperatur umschließt und interpoliere dann.

Aber durch Anwendung der Antoin-Gleichung ist ein Interpolieren eigentlich nicht nötig.
Durch die Antoine-Gleichung ergibt sich i.d.R. eine abschnittsweise definierte Funktion, die sich ja leicht umsetzen lässt (falls die Parameter gefunden wurden 😉).

mfG Gü