Laden...

Forenbeiträge von Taipi88 Ingesamt 1.029 Beiträge

13.09.2017 - 06:54 Uhr

Hi,

also vom Grundsatz:
Anbieten solltest du beides - sonst werden die User dich vermutlich tot schlagen wenn sie dich finden 😉

Was dein Problem angeht - wo ist das Problem?

Beim ersten Button-Klick startest du z.B. eine Form, die die Liste bekommt, die entsprechende Angaben einzeln anzeigt und einen Ja und einen Nein-Button anzeigt.
Ja: Drucken + nächsten Datensatz aus der Liste anzeigen
Nein: nächsten Datensatz aus der Liste anzeigen

LG

05.09.2017 - 13:02 Uhr

Hi,

einfach eckige Klammern drum rum wenn du die Tabelle ansprechen willst.

Vollständig lautet der SQL-Befehl dann ja auch eigentlich:


SELECT * FROM [DB-Name].[SCHEMA-Name].[TABELLEN-Name]

LG

04.09.2017 - 13:40 Uhr

Hi,

siehe dazu auch meinen Edit obendrüber - KP was sich Siemens da mit den Angaben zu Datentypen gedacht hat - aber die ganzen anderen Werte sind ja offenkundig byte und da du ja am Ende sicher ohnehin ein DateTime haben möchtest - kannst du das ja implizit im Konstruktor einfach nehmen als wäre es ein int. (Der Wert zu deinem Hex-String kommt bei mir als 01.09.17 - 10:38 raus, was schon sinnvoll klang)

Falls du die Nanosekunden haben möchtest - schaust du dir mal am besten nachfolgenden Link an, da DateTime eben in Ticks (= 100 Nanosekunden) rechnet.
https://stackoverflow.com/questions/5358860/is-there-a-high-resolution-microsecond-nanosecond-datetime-object-available-f

LG

Edit:
Year ist der einzige UInt16 -der Rest sind Bytes - Nanosekunden sind demzufolge UInt32.
(int ist übrigens Int32)

04.09.2017 - 13:24 Uhr

Hi,

ich sagte ja auch UInt16.

LG

PS: So würde ich das wohl lösen (ohne Nanosekunden):


using System;

namespace ConsoleApp1
{
	internal class Program
	{
		private static void Main(string[] args)
		{
			var data = new byte[] 
			{
				0x07, 0xE1, // 0,1: year
				0x09, // 2: month
				0x04, // 3: days
				0x02, // 4: weekday
				0x0A, // 5: hours
				0x26, // 6: minutes
				0x00, // 7: seconds
				0x08, 0x7F, 0xC0, 0x30 // 8-1: nanoseconds?
			};

			Console.WriteLine(data.FromDlt());
			Console.ReadLine();
		}
	}

	public static class SpsHelper
	{
		public static DateTime FromDlt(this byte[] dltArray)
		{
			if (dltArray == null || dltArray.Length < 8)
				throw new ArgumentException();
			var year = BitConverter.ToUInt16(new[] { dltArray[1], dltArray[0] }, startIndex: 0);
			return new DateTime(year, dltArray[2], dltArray[3], dltArray[5], dltArray[6], dltArray[7]);
		}
	}
}


04.09.2017 - 12:31 Uhr

Hi,

wenn ich gerade richtig recherchiert habe sind die Bytes die von der SPS kommen "unsigned" - ergo ist Int16 nur fast der richtige Datentyp - eigentlich bräuchtest du UInt16.

Denke dann kommst du auch auf die richtigen Werte.

Für alles weitere wäre die Bytefolge, sowie der daraus zu lesende Wert interessant.

LG

PS: Alles was zu diesem DTL-Format steht scheint in der SPS unsigned zu sein.

29.08.2017 - 14:21 Uhr

Hi,

@Latino - woher willst du das denn wissen? Sobald in dem Unternehmen mehr als 1 Mio Umsatz erwirtschaftet wird (oder eher uninteressant 250 PC's eingesetzt werden) wäre die Firma ja nach Lizenzbedingung ein Unternehmen und entsprechend verpflichtet zu kaufen.

Oder verstehe ich die Bedingungen falsch? 😕

Sicher - die AddIns könnte man OpenSource machen - dann wäre das ganze legal.

LG

28.08.2017 - 16:19 Uhr

Hi,

sicher geht das - und das ist auch nur ein simpler Schutz - aber es schützt zumindest vor sehr unfairer Handhabung deiner Daten.

Das Thema ist ja:
Wenn man's im Browser nicht unterbindet - dann hat einzig der Service die Traffic-Last zu alten - ohne dass z.B. über das eigene Frontend Geld mit Werbung verdient wurde - der User merkt nicht mal wo es herkommt, womit für den Asi, der das macht gerade mal noch die Last für den statischen Content bleibt. Simpelstes Beispiel: Bilder. Du machst du mit viel Mühe - und irgendwer nimmt die - aber hostet diese nicht einmal selbst sondern verlinkt einfach auf deine Ressource.

Finde das durchaus sinnvoll.

LG

28.08.2017 - 11:28 Uhr

Hi,

ohne jetzt zu fragen wofür überhaupt, das würde sich denke mich mit Action bzw. Func ganz gut umsetzen lassen. Dann kannst du sogar anonyme Methoden nehmen. Beispiel:


class Program
	{
		static void Main(string[] args)
		{
			var dic_Commands = new Dictionary<string, Action>
			{
				[key: "Test1"] = () => Console.WriteLine(value: "Bla1"), // anonym
				[key: "Test2"] = Test2 // eigene methode
			};

			dic_Commands[key: "Test1"].Invoke();
			dic_Commands[key: "Test2"].Invoke();
			Console.ReadLine();
		}

		private static void Test2()
		{
			Console.WriteLine(value: "Bla2");
		}
	}

LG

PS:
Action gibt's auch Action<T> (hat dann Argumente)
An Stelle von Action kannst du auch Func<> verwenden wenn die Methoden Argumente und einen Rückgabewert brauchen.

28.08.2017 - 09:59 Uhr

Hi,

naja - das Ganze soll eigentlich deine Backend-Daten schützen - so, dass die Daten von deinem Backend eben nur vom Backend und auch vom erlaubten Frontend abgerufen werden können. (Jedenfalls direkt z.B. im Browser via Ajax)

Beispiel:
Du baust ein Frontend und ein Backend für eine Wettervorhersage, baust das ganze ordentlich mit Ajax auf.

Ohne CORS:
XYZ findet die Idee cool - setzt ein Frontend auf - und nutzt ohne Erlaubnis dein Backend.

Mit CORS:
Dein Backend sagt: ist nur für mein Frontend gedacht.

LG

@mfe: Gegen XSS war das nicht gedacht wenn ich mich recht entsinne...

18.08.2017 - 20:18 Uhr

Hi,

du kannst mal nach dem PredicateBuilder schauen - wenn ich mich recht entsinne kann man den für sowas einsetzen.

Allerdings hast du auch wichtigere Baustellen:
a) Du willst doch hoffentlich nicht wirklich so deine UI aufstellen?!
b) Wenn du nicht dazu gezwungen wirst - vermeide String-Frickelei - und brock sie dir nicht noch selbst ein... Bau dir eine Klasse für Suchbedingungen - dann würde ich an deiner Stelle erst nach dem PredicateBuilder suchen
c) case 0: kannst du dir dank default: sparen

LG

17.08.2017 - 11:18 Uhr

Hi,

mit Environment.NewLine bekommst du einen String, der einen Zeilenumbruch hervorruft.

LG

17.08.2017 - 11:14 Uhr

Hi,

naja - da wird die lame.exe wohl noch ein Handle drauf haben.

Vorschlag: Versuch doch mal mit Process.WaitForExit auf die Lame.exe zu warten anstatt die einfach abzuschließen... (Das Thread.Sleep ist allemal nur ein sehr hässlicher Hack)

LG

10.08.2017 - 12:59 Uhr

Hi,

mal für den Fall, dass du wirklich 24bpp brauchen solltest - was genau dauert denn eigentlich zu lange? Sicher die Konvertierung?

Falls dem so wäre - probier mal AForge.Imaging - damit geht GrayScale to 24bpp-RGB (ohne Coloring) so:


var filter = new GrayscaleToRGB();
var rgb = filter.Apply(img);

Alternativ kannst du auch direkt mal folgendes Beispiel anschauen:
https://gist.github.com/xinmyname/1602389

LG

09.08.2017 - 16:23 Uhr

Hi,

grundsätzlich verstößt du gegen die Forenregeln, wenn du die Grundlagen nicht beherrschst bzw. auch selbst keinen Aufwand darin investierst es zumindest selbst in C# zu versuchen.

Wir sind ja schließlich keine Code-Übersetzungsmaschinen. Zumal das Beispiel in C++ ja auch unvollständig ist.

Grundsätzlich:
a) Der enum würde auch in C# funktionieren
b) Davon ausgehend, dass du ein Konsolenprogramm schreiben möchtest - erstellst du per VisualStudio besser mal eine Konsolenanwendung - baust deinen enum ein - und schaust dir einfach mal Die Methoden der statischen Klasse "Console" an.

Ich bin mir recht sicher, dass du damit zurecht kommst.

LG

PS: Wenn du kurz Sachen wie z.B. enum nachschlagen musst: http://openbook.galileocomputing.de/visual_csharp_2012/

PPS: Objektorientierung wäre sicher auch nicht verkehrt: http://openbook.galileocomputing.de/oop/

08.08.2017 - 15:34 Uhr

Hi,

mir stellt sich ehrlich gesagt auch die Frage, was du mit dieser Abfrage überhaupt beabsichtigst 😕

Wenn du Personen nach Namen filtern möchtest - brauchst du keine gesonderte Liste von Namen. Vor allem - warum 2 x from? Willst du gruppieren? Oder nach den Bedingungen aus "bla" filtern?

Mal ausgehend von letzterem:


var bla = from name in namen where name.StartsWith("H") select name;
var treffer = personen.Where(p => bla.Contains(p.Name));
// alternative:
var treffer2 = personen.Where(p => p.Name.StartsWith("H"));

Grundsätzlich besteht gerne die Möglichkeit, dass Schlicht das Property Name der Klasse Person null ist...

LG

08.08.2017 - 15:18 Uhr

Hi,

doch das spielt eine Rolle - du startest nämlich damit eine alte Version deines Programms, womit deine aktuellen Änderungen keine Rolle spielen.

Grund für die 4 Fehler sind die einfach von dir entfernen Ereignisbehandlungsmethoden.

Wenn du in deine Form2.Designer.cs-Datei reinschaust (ist hinter Form2.cs versteckt) wirst du 4 rot markierte Anweisungen finden die du löschen musst.
Sehen ungefähr folgendermaßen aus:


Xl_ylog.CheckedChanged += Xl_ylog_CheckedChanged;

Das kommt daher, dass der Designer nicht riechen kann wenn du in deiner Code-Datei was löschst.

Ich denke wenn du das korrigiert hast - ist auch der Fehler weg - falls nicht - kannst du schauen, ob es hilft, wenn du im Konstruktor (nach InitializeComponent) folgendes quasi als Startwert schreibst:


Xy_l.Checked = true;

LG

PS: Wenn du Fehlermeldungen bekommst - lies diese besser genau 😉

08.08.2017 - 13:08 Uhr

Hi,

so wie ich das sehe hast du im SessionParameter schlicht keinen Zugriff auf ein Property innerhalb einer SessionVariable, welche ja auch eher für direkte Werte gedacht sind.

Auf folgender Seite sind Beispiele verlinkt:
https://stackoverflow.com/questions/9399522/how-to-get-a-value-for-an-asp-net-session-parameter-from-property-of-session-obj

LG

08.08.2017 - 12:46 Uhr

Hi,

du hast leider auch nicht so implementiert wie ich das empfohlen hatte 😉

Wundert mich ehrlich gesagt, dass da überhaupt was funktioniert, da der Setter (den du weglassen solltest) hier nicht einmal aufgerufen wird. Richtig wäre:


public string Kal
{
	get
	{
		if (Xy_l.Checked)
			return "1";
		if (Xl_ylog.Checked)
			return "2";
		if (Xlog_yl.Checked)
			return "3";
		return "4";
	}
}

LG

PS: Es ist sehr befremdlich, dass du Zahlen als String überträgst. Wieso eigentlich kein int?

PPS: Properties die keine zusätzlichen Sachen in getter und setter machen kann man übrigens auch vereinfacht folgendermaßen schreiben:


public decimal X_max {get;set;}

08.08.2017 - 10:57 Uhr

Hi,

in meinen Augen ist das Property "Kal" eigentlich nicht die verkehrte Wahl.

Form2 sollte Form1 nicht einmal kennen -> hälst du ein.
Die Nutzung eines Events bringt dir hier keinen Vorteil.
Die RadioButtons von Form2 in Form1 direkt zu benutzen wäre unklug.

Allerdings lässt sich die Implementierung des Properties und der Form sehr viel einfacher gestalten indem du die ganzen EventHandler für die Checkboxen weglässt, den Setter von "Kal" weglässt und den Getter so implementierst, dass kurz die Checkboxen abgefragt werden.

LG

07.08.2017 - 15:36 Uhr

Hi,

hast du dir die Homepage von denen mal angeschaut?

Da steht eigentlich alles: https://www.fast-report.com/public_download/FRNetProgrammerManual-en.pdf

Was mir jedoch auffällt ist, dass scheinbar nur bis Visual Studio 2015 supported wird wenn man der Homepage glauben möchte. Würde mich abstoßen - entweder das Produkt wird nicht länger wirklich weiterentwickelt - oder das Unternehmen pflegt die Homepage ziemlich schlampig.

LG

07.08.2017 - 06:59 Uhr

Hi,

mit 2 Tipps könnte man dir sicher helfen.

a) Wenn du hier Code postest - dann verwende bitte Code-Tags (das durcheinander will sonst keiner lesen)
b) Dein Problem sehe ich auf den ersten Blick in dieser Form nicht - allerdings ist das kein Problem, denn wo auch immer es liegt - der Debugger wird dir hier weiterhelfen was dir hier entgangen ist. Einfach mal durchsteppen.

Anleitung: [Artikel] Debugger: Wie verwende ich den von Visual Studio?

LG

04.08.2017 - 10:01 Uhr

Also hast du Code. Unter anderem Code der schon SQL-Befehle abschickt.

Kurzform: Deine Abfrage ist falsch bzw. passt nicht zur Datenbank.

Vorgehensweise: Schreib den richtigen Tabellennamen in deinen SQL-Code.

LG

04.08.2017 - 09:56 Uhr

Hi,

dann kann man eigentlich nur ein Buch empfehlen, wie z.B. das http://openbook.galileocomputing.de/visual_csharp_2012/

LG

04.08.2017 - 09:53 Uhr

Hi,

ohne konkretes Problem wird dir hier niemand weiterhelfen.

Wir schreiben nicht anderer Leute Projekte.

Würde dir somit empfehlen es zumindest zu versuchen und eventuell auftretende Probleme hier anzufragen.

LG

04.08.2017 - 09:36 Uhr

Hi,

noch ein Hinweis:

Was du machen möchtest ist ein HTTP-Request über TCP wenn ich mich nicht irre.

Was du machst? Einen UDP-Request.

So wie ich das sehe würde ich dir eine Google-Suche nach "c# query json web api" weiter helfen.

LG

Edit: Sry - UDP übersehen. Wer macht denn sowas?

04.08.2017 - 08:09 Uhr

Hi,

möchte mir auch ein paar Hinweise erlauben.

  1. Pfade baut man mit Path.Combine zusammen
  2. Du verwendest nirgends irgendwelche code-doku (in wenigen wochen musst du schon selbst jede Methode komplett lesen um zu wissen was diese überhaupt macht)
  3. Deine Controls tragen zusätzlich zur fehlenden doku oft noch ihren Standard-namen
  4. Wenn du eine einzige Variable hättest, in der jeweils der aktuelle Pfad stehst fällt unglaublich viel Code bei dir einfach weg (unter anderem kannst du alle Methoden die Prozesse starten, sowie alle Methoden die die Daten in die Combobox packen jeweils auf eine reduzieren
  5. Für Directories sollte man konsequenterweise auch die Klasse DirectoryInfo und nicht FileInfo nutzen

LG

03.08.2017 - 11:53 Uhr

Hi,

soweit ich das verstanden habe - kann man dieses Problem allerdings auch dadurch relativieren, dass man die Lifetime der Connections verändert, dass beispielsweise das Problem damit maximal auf 60 Sekunden nach dem Vorfall beschränkt wird, was ja schon mal eine erhebliche Verbesserung darstellen würde.

LG

03.08.2017 - 10:53 Uhr

Hi,

ganz ehrlich - wenn du kein MVVM machen möchtest - dann nimm lieber WinForms - das ist für Frickelcode einfacher.

Was dein eigentliches Problem angeht - du scheinst hier offenkundig irgendwas am Prinzip deiner Objekte und Klassen zu übersehen.

Wenn dein Window erstellt wird - wird in der Tat nur ein einziges mal der Konstruktor aufgerufen. Wenn der Konstruktor allerdings nicht von dir geschrieben ist der dort aufgerufen wird - dann machst du etwas falsch. Was genau kann man ohne Code nicht sagen.

Wenn dein MainWindow per App.xaml erstellt wird - wird dort der nackige Konstruktor ohne jeglichen Parameter verwendet. Soweit der Standard.

Ganz ehrlich - Windows die per XAML erstellt werden sollten keine Konstruktorparameter verlangen. Alternativ wäre es auch möglich entsprechende Rahmenparameter aus der Anwendungskonfiguration zu ziehen.

Noch ganz anders - für deinen Fall allerdings nicht sinnvoll wie ich finde (vorgenannte Variante ist flexibler wie hart codierte Parameter) ist die Erstellung einer eigenen Program.cs mit normaler Main-Methode, die dann eine Instanz deiner umprogrammierten App.xaml.cs erstellt, worin du dann selbst dein Window erstellen kannst.

LG

03.08.2017 - 09:13 Uhr

Hi,

ist zugegebenermaßen etwas frickelig - aber folgendermaßen mache ich das:
(nur als Beispiel)


ublic override IEnumerable<CompoundIdentityResource> GetAllCompound()
		{
			var command = $"SELECT * FROM {TableName} AS iRes" +
			              $" LEFT JOIN {UnitOfWork.DapperDataService.NameService.NameByType(typeof(IdentityResourceClaimEntity))} AS iClaim" +
			              $" ON iRes.{nameof(IdentityResourceEntity.Id)} = iClaim.{nameof(IdentityResourceClaimEntity.IdentityResourceId)}" +
			              $" LEFT JOIN {UnitOfWork.DapperDataService.NameService.NameByType(typeof(IdentityResourceScopeEntity))} AS iScope" +
			              $" ON iRes.{nameof(IdentityResourceEntity.Id)} = iScope.{nameof(IdentityResourceScopeEntity.IdentityResourceId)}" +
			              $" LEFT JOIN {UnitOfWork.DapperDataService.NameService.NameByType(typeof(ScopeEntity))} AS scope" +
			              $" ON iScope.{nameof(IdentityResourceScopeEntity.ScopeId)} = scope.{nameof(ScopeEntity.Id)}";
			var lookup = new Dictionary<int, CompoundIdentityResource>();
			UnitOfWork.Connection
				.Query<IdentityResourceEntity, IdentityResourceClaimEntity, IdentityResourceScopeEntity, ScopeEntity,
					CompoundIdentityResource>(command,
					(entity, identityClaim, identityScope, scope) =>
					{
						// make sure the pk exists
						if (entity == null || entity.Id == default(int))
							return null;

						// make sure our list contains the pk
						if (!lookup.ContainsKey(entity.Id))
							lookup.Add(entity.Id, new CompoundIdentityResource
							{
								IdentityResource = entity
							});

						// fetch the real element
						var tempElem = lookup[entity.Id];

						// add identity-scope
						if (identityScope != null)
							tempElem.IdentityResourceScopes.Add(identityScope);

						// add claim
						if (identityClaim != null)
							tempElem.IdentityResourceClaims.Add(identityClaim);

						// add scope
						if (scope != null)
							tempElem.Scopes.Add(scope);

						return tempElem;
					}, param: null, transaction: UnitOfWork.Transaction);
			return lookup.Values;
		}

LG

02.08.2017 - 13:56 Uhr

Hi,

nein - du möchtest kein DataGrid exportieren.

Du möchtest die Daten des DataGrids exportieren - und wenn du brav nach MVVM arbeiten würdest - dann wäre auch dein DataGrid an eine entsprechende Collection gebunden.

Mach's ordentlich - dann erledigt sich dein Problem alleine.

LG

02.08.2017 - 09:11 Uhr

Hi,

naja - das TabControl hat ein DependencyProperty namens "ItemsSource", dass du an eine entsprechende Liste von Kurven binden solltest.

Dann noch darein ein hübsches Template und voila 😉

Google einfach mal nach TabControl ItemsSource Template.

LG

01.08.2017 - 07:51 Uhr

Hi,

zum Verständnis:

Repository:
Ein Repository ist bei mir eine Klasse, die zur Verwaltung von Instanzen einer bestimmten Entität, wobei eine Entität im einfachsten Fall direkt einen Eintrag einer Tabelle beschreibt.

UnitOfWork:
Einfach ein "Arbeitsschritt", der ggf. mehrere Datenbankaktionen (ergo: mehrere Funktionsaufrufe eines oder mehrerer Repositories) miteinander verbindet.

Beispiel UnitOfWork:
Sinn macht das speziell wenn du z.B. die Entitäten "Kunde" und "Adresse" hast, wobei Kunde z.B. nur die Namen enthält (Name1, Name2, Name3 + Fremdschlüssel auf Adresse) und Adresse enthält die genauen Adressdaten (Straße, PLZ, Ort). Deine UnitOfWork soll jetzt einen Kunden anlegen - zu diesem Kunden gehört allerdings auch logischerweise eine Adresse. (Ergo: 2 Inserts, die nur gemacht werden sollen wenn auch wirklich beide klappen)
Von der Logik her - würde man nun zuerst die Adresse und dann den Kunden einfügen.

Fall a) (wenn du keine gemeinsame Transaktion nutzt)
Nun machst du zuerst den Insert für die Adresse -> klappt
Danach den Insert für den Kunden -> geht schief
Endergebnis: In deiner DB ist eine Adresse als "Leiche"

Fall b) (wenn du eine gemeinsame Transaktion nutzt)
Nun machst du zuerst den Insert für die Adresse -> klappt
Danach den Insert für den Kunden -> geht schief
Endergebnis: Durch ein Rollback der Transaction wird die Adresse gar nicht erst endgültig gespeichert und es bleibt dadurch keine Datenbankleiche übrig.

In jedem Repository eine eigene Connection zu erzeugen ist insofern doof und teilweise auch gefährlich, weil du schnell mehrere dutzend Connections machst.

Mal ohne die ganzen Schnittstellen aus meiner Umsetzung wäre somit das Minimum:

UnitOfWork:
Erzeugt bei Instanziierung:
a) eine IDbConnection unfd öffnet diese
b) erstellt auf die Connection eine Transaction
c) Implementiert IDisposable für automatisches Commit bzw. Rollback, damit z.B. folgendes geht:


using (var uow = new DapperUnitOfWork())
{
var adressRepo = new AdressRepository(uow);
adressRepo.Insert(myAdress);
var customerRepo = new CustomerRepository(uow);
customerRepo.Insert(myCustomer);
uow.Commt();
}

Bei Implementierung von IDisposable die z.B. folgendermaßen aussehen könnte:


public override void Dispose()
		{
			Dispose(disposing: true);
		}
protected virtual void Dispose(bool disposing)
		{
			if (Transaction != null)
				Rollback();
		}
public override void Commit()
		{
			if (Transaction == null)
				throw new InvalidOperationException(
					message: "UnitOfWork can't be committed since it's already finished. (Missing transaction)");
			Transaction.Commit();
			Transaction.Dispose();
			Transaction = null;
			Connection.Dispose();
			Connection = null;
		}
public override void Rollback()
		{
			if (Transaction == null)
				throw new InvalidOperationException(
					message: "UnitOfWork can't be rolled back since it's already finished. (Missing transaction)");
			Transaction.Rollback();
			Transaction.Dispose();
			Transaction = null;
			Connection.Dispose();
			Connection = null;
		}


hast du es dann so implementiert, dass wenn irgendwas innerhalb des Usings schief läuft - automatisch nichts in der Datenbank von dem fehlgeschlagenen Versuch übrig bleibt.

Grundsätzlich lassen sich die CRUD-Funktionen komplett in einem generischern Repository verankern. (Würde ich abstrakt machen) - und die eigentlichen Repositories erben dann davon und erweitern dieses Repository nach Bedarf.

Tipp für das generische Repository:
Mit Hilfe von Dapper.Contrib.Extensions musst du dafür nicht einmal SQL zusammenbasteln.

Zur Connection: das würde ich in einer sogannten Factory auslagern an deiner Stelle.

Hab dir mal ein Minimalbeispiel gemacht damit du siehst, was ich meine. (Benötigte nuget-Packages: Dapper, Dapper.Contrib)

LG

31.07.2017 - 12:17 Uhr

Hi,

im Prinzip recht einfach - wenn du dir den Designer-Code anschauen würdest wäre es offensichtlich.

Die Komponenten werden initialisiert (durch deinen Konstruktor) - dabei wird bevor die TextBox initialisiert wurde - das SelectionChanged-Event ausgelöst und es knallt.

Die einfachste Variante da drumherum zu kommen ist das SelectionChanged-Ereignis selbst zu abonnieren - und zwar nach dem Aufruf von "InitializeComponent".
(Und ebend das Ereignis-Abonnement wie's im Designer eingestellt wurde entsprechend zu entfernen)

LG

31.07.2017 - 12:05 Uhr

Hi,

Repository-Pattern ist bei mir mit dem UnitOfWork-Pattern auf Basis von Dapper umgesetzt.

Und die UnitOfWork-Instanz ist dann auch der ideale Platz um so eine IDbConnection (und besser auch die Transaction) zu halten und an Repositories weiterzugeben.

Gibt dann einen DataService, der die UnitOfWork (und ggf. auch die Repositories) erzeugt - die Repositories bekommen dann jeweils einfach die UnitOfWork.

Wenn du ein Beispiel brauchst kannst du auf folgendem Link mal reinschauen:
https://github.com/IInvocation/AppFx/tree/master/src/FluiTec.AppFx.Data.Dapper

(Ist sicher noch verbesserungswürdig - bin kein Profi)

LG

PS: Das mit dem DRY ist übrigens dann nicht dein einziges Problem - gibt ja oft sachen, wo evtl. mehr als ein Repository beteiligt ist - wenn die verschiedene Transaktionen verwenden und was nicht perfekt sauber abgefangen wird schreibst du evtl. sogar inkonsistente Datensätze, weil die Repositories keine gemeinsame Transaction hatten...

PPS: Bevor du Klassen mehrfach schreibst - definitiv in's API-Projekt schieben.

23.07.2017 - 18:37 Uhr

Hi,

dein aktuelles Problem lässt sich mit partiellen Klassen lösen.
File1:


public partial class Form1 : Form
{
...whatever
}

File2:


public partial class Form1 : Form
{
...whatever2
}

Nichts desto trotz solltest du es lassen. Warum ist recht einfach erklärt - C# ist wie Java objektorientiert - man benutzt Klassen um Funktionalität zu bündeln. Diese Klassen kannst du dann wiederum in deiner Form benutzen.

Wenn du ein File hast, bei dem du das Bedürfnis hast dieses mit "partial" aufzuteilen - hast du in 99% der Fälle mies programmiert, was du dir besser gleich abgewöhnst 😉

LG

20.07.2017 - 15:21 Uhr

Hi,

ich muss jetzt ehrlich mal anmerken, dass dir ein Buch gut tun würde.

Du meinst sicher eine for oder foreach Schleife. Einfach googeln.

LG

Link OpenBook: http://openbook.galileocomputing.de/visual_csharp_2012/

20.07.2017 - 11:27 Uhr

Hi,

davon ausgehend, dass du Controller, Views, etc. aus anderen Assemblies meinst hast du scheinbar nicht sauber gegoogelt.

Folgendes habe ich gefunden:

LG

PS: Beispielsweise für Repositories ist DependencyInjection angesagt und bereits im Standard vorhanden.

PPS: Ggf. wäre einer solchen Modularisierung aber auch eine Architektur von Microservices entgegenzustellen, die ggf. separat laufen. (Mal abgesehen vom View-Teil)

PPPS: Für Daten würde ich ehrlich gesagt auch Dapper in Betracht ziehen. Ist natürlich kein ORM - aber mit minimalem Einsatz lässt sich sehr einfach das Reposiory-Pattern und/oder UnitOfWork-Pattern einbauen und man muss nur noch recht wenig SQL schreiben. Bin mittlerweile ein wenig von ORM's weg, da ich gerade bei komplizierteren Aufgaben oft das Gefühl hatte diese zu vergewaltigen zu müssen - mal abgesehen vom Overhead der oft schlicht nicht benötigt wird...

19.07.2017 - 13:22 Uhr

Hi,

Threads sind halt wie bereits von mir beschrieben ein üblicher Teil des Betriebssystems und essenziell, womit C# das natürlich unterstützen muss. (und sicher auch von Beginn an tat)

Tasks dahingehen sind ein neueres Konzept, die vieles einfacher machen - im Inneren aber dennoch Threads verwenden (können).

Für Threads kannst du dir folgendes ja mal anschauen:
https://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx

Wenn du Oberflächen schreibst - ist MultiThreading eigentlich nur in den seltensten Varianten uninteressant. Ob du nun eine WebRequest machst, eine Datei ausliest, Datenbank-Daten sammelst, oder ggf. sogar Signale von Geräten annehmen musst, etc. pp. - all das sollte nicht auf dem GUI-Thread stattfinden.

Was deine Ambitionen mit "Klick-Oberflächen" angeht - ist sicher deutlich übersichtlicher mit C# - der GC dürfte hier auch helfen. Nichts desto trotz:
Wenn du dir viel Arbeit ersparen willst - nimm den Link zum Online-Buch (von M.L.) und arbeite es erst mal durch - dann gewinnst du zumindest einen Überblick über das .NET-Framework, C# und entsprechende Features.

LG

19.07.2017 - 12:40 Uhr

Hi,

nein es geht nicht nur um UI-Oberflächen - Tasks und Threads sind sicher auch bei Konsolenanwendungen interessant - wär doch ziemlich blöd, wenn du eine Aufgabe startest die mindestens mal 10 Minuten dauert - und in der Zwischenzeit nichts anderes mit der Anwendung machen kannst, weil du nur einen Thread benutzt.

Das Thema ist:
Startest du eine Anwendung - wird immer auch mindestens ein Thread gestartet für das Programm. Das ist der Hauptthread, den z.B. GUI und Konsole benutzen. Und damit dort weiterhin was passieren kann - selbst wenn du parallel iwas machst was halt richtig lang dauert oder auch nur die Eingabe verzögern würde - nutzt man Tasks und Threads.

Damit in einer Oberflächenanwendung das Fenster "einfriert" (nicht mehr reagiert) muss nicht die CPU überlastet sein - es reicht durchaus wenn du eine 5MB-Datei einliest und das aus welchen Gründen halt auch immer das z.B. 5 Sekunden dauert - und der User in diesen 5 Sekunden was mit deinem Fenster machen möchte - dass dein Fenster schlicht nicht reagieren kann, weil ja dein Thread mit was anderem beschäftigt ist. In diesem Fall merken das sowohl Windows als auch der User, was ja nicht gewollt ist. (Wenns all zu lang dauert bietet Windows hier sogar an dein Programm abzuschießen)

LG

Nachtrag 1 (ein weiteres Beispiel für Multithreading):
Es kann ja auch durchaus vorkommen, dass du auf Basis vorhandener Daten zwei von einander unabhängige Berechnungen vornehmen möchtest, die allerdings jede für sich 20 Minuten dauert.
Ohne Multithreading - dauert das ganze also 40 Minuten. Mit Multithreading: ca. 20 Minuten - einfach weil dein Computer ja mehr wie nur eine Sache auf einmal kann - dein Programm muss dies allerdings halt unterstützen. (Würde dir hier wirklich mal Wikipedia zu Multithreading empfehlen) - hab die Oberfläche nur benutzt, weil das üblicherweise der erste Punkt ist an welchem man mit Multithreading aus der beschriebenen Problematik zusammenstößt.

PS: Bin auch mehr oder minder Hobby-Entwickler - jedenfalls kein Profi - würde jedoch auch empfehlen das Lehrmaterial auf die Gegebenheiten abzustimmen - andernfalls wirst du nicht weit kommen bzw. vor Frust eher aufhören...

19.07.2017 - 10:52 Uhr

Hi,

na wenn's nicht funktioniert wie du möchtest wäre ein Codebeispiel ja sinnvoll.

Unabhängig davon solltest du berücksichtigen:
a) Multithreading für Datei-Operationen lohnt sich selten
b) Von einem nicht UI-Thread auf die UI zuzugreifen wird so nicht funktionieren

LG

19.07.2017 - 07:01 Uhr

Hi,

nun - wenn du denn wirklich an 2008 gebunden bist - sei's drum.

Bei System.Threading.Tasks geht es um eine Art Abstraktionsschicht für's Multithreading.
(Sprich: Deinen Computer mehrere Sachen auf einmal machen lassen für dein Programm)

Ein Task ist eine Aufgabe, die zumeist asynchron über einen anderen Thread läuft und so den Hauptthread deiner Anwendung nicht blockiert. (Das macht man z.B., damit die Anwendung längere Operationen ausführen kann - die Oberfläche aber dennoch weiter funktioniert - ohne würde es z.B. vorkommen, dass deine Oberfläche schlicht einfriert)

Tasks machen im Endeffekt das Arbeiten mit asynchronen Programmabläufen um ein Vielfaches einfacher - du wirst es deshalb nicht einfach haben asynchron zu programmieren.
Es geht allerdings auch durchaus auch ohne diese Vereinfachung. Findest sicher im Web noch hunderte Artikel wie das sauber mit eigens erstellten Threads funktioniert.

Unabhängig davon:
Wenn du programmieren lernen möchtest - solltest du dir Gedanken darüber machen für wen du später programmieren möchtest. C# hat sich seit 2008 doch stark weiter entwickelt - all die "modernen" Sachen gehören längst zum Standard - und wir reden hier durchaus nicht nur von Sachen von Tasks. Des Weiteren gilt Windows XP immer noch als Sicherheitsrisiko. Obendrauf kommt: Wenn du mit .NET 3.5 arbeitest - machst du es Usern mit Windows 10 nicht leichter deine Programme zu nutzen 😉 Du wirst dir halt beim Lernen keinen Gefallen tun - weil all die Google-Resultate schon neue Features verwenden die du nicht kennst und auch nicht einfach abschreiben kannst - sondern du diese oft auf .NET 3.5 abwandeln musst.

Aber: Deine Entscheidung.

LG

18.07.2017 - 14:20 Uhr

Hi,

naja - wie dein ConnectionString aussehen muss kannst du z.B. auf folgender Seite gucken:
https://www.connectionstrings.com/sql-server-2012/

Was deine App.Config angeht - Es gibt immer nur eine - für ASP.NET heisst das allerdings Web.config. (heisst: nimm die Web.Config deines letztendlich zu startenden Projekts)

Innerhalb dieser Web.Config - musst du entsprechende Eintragungen machen - wie die aussehen - können wir nicht wissen.

Üblicherweise enthält dein .DataAccess-Projekt allerdings wahrscheinlich eine App.config, an deren Beispiel du dich langhangeln kannst.

Dazu gehört: Das definieren einer entsprechenden Section, wie z.B.:

<section name="EasySoftener.Wcf.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />

Und dann entsprechende Einträge für die Section:

<applicationSettings>
    <EasySoftener.Wcf.Properties.Settings>
      <setting name="SmtpUser" serializeAs="String">
        <value>...</value>
      </setting>

LG

18.07.2017 - 12:17 Uhr

Hi,

naja - du gibst nun echt zu wenig Input.

Aber: Unter der Vermutung, dass du den IIS einsetzt - wird hier vermutlich dein IIS-User eingesetzt. Sofern du für die Website einen eigenen Pool und einen eigenen User hast (wie's sich gehört) - solltest du diesem lieber die nötigen Rechte geben als was im ConnectionString zu machen.

LG

18.07.2017 - 06:44 Uhr

Hi Neuer,

naja - einfach mal in C# Plugins für irgendwelche Games schreiben wird in 99% der Fälle schlicht nicht gehen - dafür müssten die Spiele eine entsprechende Schnittstelle bieten.

Gerade heraus: Für dein Ziel scheint C# lernen nicht der richtige Weg - da würde ich mich eher bei Moddern erkundigen...

LG

17.07.2017 - 16:29 Uhr

Hi,

naja - auf den ersten Blick passt der Name des Parameters nicht.

VATERID // ElternId

Wenn ich mich recht entsinne macht das durchaus Ärger.

LG

12.07.2017 - 14:15 Uhr

OT:
Ohne COM-Addins wird es allerdings sicher einige geben die da keine Lust drauf haben... Angefangen bei den Addins für CTI-Applikationen über etliche Komfortfunktionen wie Schnelldruck von Anhängen... Hoffe jedenfalls, dass die Möglichkeit bestehen bleibt.

11.07.2017 - 16:02 Uhr

Hi,

so langsam versteh ich deinen Haken aber nicht.

Du brauchst eben noch eine GUI für das Erfassen/Bearbeiten/Löschen von Servergruppen und Servern.

Die Klassen? Die sind für mehrere Sachen nützlich:
a) Ein paar eigene Klassen würden deinem Programm sicher gut tun 😉
b) Die Klassen können im Zusammenhang mit DataBinding für die GUI genutzt werden
c) Die Klassen und die List<ServerGroup> ersparen dir durch Nutzung von Serialisierung/Deserialisierung das Schreiben eines eigenen Parsers. Da du mit Hilfe von Serialisierung aus einer List<ServerGroup> ein XML-File machen kannst - und mit Hilfe von Deserialisierung geht's dann auch umgekehrt.

LG

11.07.2017 - 12:12 Uhr

Hi,

grad die App.config-ConnectionStrings halte ich in diesem Fall für den falschen Weg, weil du hier keine eigene Struktur basteln kannst. (Speziell Gruppen etc.)

Was das Eingabeformat angeht:
Schreib die o.g. Klassen - eine entsprechende Oberfläche und lass die User besser nicht im XML rumpfuschen. Ich denke du baust für den DAU? Dann baut man eben eine hübsche Oberfläche zum Verwalten der Server mit allen nötigen Prüfungsroutinen.

LG

PS: App.config liegt zudem entweder im Verzeichnis des Programms (Admin-Rechte zum Editieren benötigt - keine gute Idee) oder wenn User-bezogen eben in einem User-Verzeichnis, was das Nutzen einer Liste für Alle unmöglich macht.

11.07.2017 - 11:38 Uhr

Hi,

klar gibt es die - das einfachste wäre:
a) Eine klasse "Server" mit den Properties

  • Server
  • Database
  • UID
  • Password

b) Eine Klasse "ServerGroup" mit den Properties:

  • Name
  • Servers (List<Server>)

c) Eine Liste List<ServerGroup>

Das ganze serialisiert/deserialisierst du und fertig. (Siehe z.B. https://msdn.microsoft.com/de-de/library/58a18dwa(v=vs.120).aspx)

LG