Laden...
S
spike24 myCSharp.de - Member
Programmierer Steiermark Österreich Dabei seit 01.02.2008 443 Beiträge
Benutzerbeschreibung

Forenbeiträge von spike24 Ingesamt 443 Beiträge

11.10.2011 - 11:56 Uhr

Hi,

Das funktioniert nur solange, wie der Entwickler absolute "Basic-SQL-Statements" schreibt. Sobald irgendeine spezifische DB-Funktion im SQL-String vorkommt, klappt es nicht mehr.

Ich habe beim entwickeln meines ORMappers die Frage von mir geschoben.
Mein Ziel war einen ORMapper zu bieten der zu jeder datenbank passt und die möglichkeiten jeder Datenbank ausnützt. (geht ja nicht)

also habe ich mir einen "Dummen" ORMapper geschrieben, der Intern für jeden Datenbank einen "Connector" hat.
dieser connector liefert eigentlich nur SQLStrings die gegen die Datenbank gefahren werden können.
Die SQLStrings werden aus meinen "Dto" Dateien ausgelesen. Diese Datei ist mit Attributen vollgestopft. (TableMappingAttribute, FieldMappingAttribute, PrimaryKeyattribute, ForeinKeyAttribute, etc)
Mit dieser Vorgehensweise kann ich bei einem einzelnen Select auch JOIN befehlen zusammen bauen. Wie ein JOIN aussehen muss weis der connector, was er joinen muss kann er aus bekommt er vom ORMapper ausgelesen.

Damit bin ich Datenbank unabhängig solange ich nur SELECT UPDATE und DELETE verwende. Genügt für den grösseren Teil den die Anwendung braucht.

Es genügt aber nicht für alle Programme und dafür habe ich ein neues Attribut erfunden, das CommandAttribute
dieses CommandAttibute kann clientseitig verwendet werden um einen SQL-Procedure aufzurufen.
Damit ist der Verwender des ORMappers in der Verantwortung sich einen umstieg auf eine andere Datenbank zu erschweren. Nicht mehr Deine.

Durch eigene connectoren die sich die SQL-Befehle zusammen bauen, machst Du Dir schon recht viel datenbank unabhängigkeit ohne auf features der datenbank zu verzichten.

hoffe der Text war verständlich.

lg
RR

15.09.2011 - 10:20 Uhr

Das sowetwas kommen wird steht für mich ausser Frage. Ich bin/war selbst Pendler, früher an die 1.200 km pro Woche und wenn man da in die Stadt fährt werden da Probleme auf uns zukommen die fast nur so gelöst werden können.

Aber wie da schon ein paar mal erwähnt, der Umstieg könnte da ein Problem werden.
3 automome Fahrzeuge, und 27.000 andere.
Genau genommen braucht ein Automatisches Fahrzeug eigentlich nur lenken, bremsen und gasgeben.
Selbst relative simple Tätigkeiten, aber einem Auto das ales ganzes beizubringen ist aber schon schwieriger. Was ich mir vorallem für Autobahnen (hier sehe ich den grössten Sinn) als lösung sehen könnte ist: nicht das das Auto autonohm fährt, sondern die Strasse weis wieviele Autos unterwegs sind und den Autos selbst weiter gibt, was es tun soll.
So Radartechnik an den kleinen Lichtern am Strassenrand und WLAN zum kommunizieren mit den Autos selbst.
Würde von aussen gleich aussehen und in den Autos würde mehr oder weniger ein kleiner Empfänger sein der das Lenkrad und die zwei Pedalen bedienen kann.

Das würde meiner Ansicht nach sehr viel bringen, vorallem wenn ich daran denke wie ich immer nach Wien gefahren bin. Ne kleine Gruppe, Windschatten fahren mit Geschwindigkeiten die in Deutschland auch nicht erlaubt wären.
Laut Studio gehöre ich zu den Menschen die am wenigsten Unfälle (pro km) haben, aber am meisten Strafen haben. Andere kaufen sich darum ein Auto für das was ich dem Stadt schon gezahlt habe 😦

01.08.2011 - 13:54 Uhr

Auch wenn ich in meinem Ersten Post davon gesprochen habe, das in einem Studium manchmal unqualifiziertes Personal produziert wird, sehe ich es absoluten Vorteil an wenn man ein Studium hat.

Wie einer der Vorredner sagte es liegt am Individuum!
Wenn einem Programmiern (Software entickeln) gefällt wird er die Studienzeit nützen und sich neben dem Studieren die, von einigen bemägelte fehlende Praxis, aneigenen.

Wenn er mit dem Studium fertig ist, privat einen ->funktionierenden<- ORMapper geschrieben hat, vielleicht dazu ein passenden WCF-Service, dann bekommt er jeden Job für den er sich bewirbt. Zumindest ich nehm so einen mit Handkuss und der erste Kaffee geht auf mich.

Fazit: Wenn man es richtig macht (mit Ehrgeiz!), dann ist das die best investierte Zeit in Deinem Leben

26.07.2011 - 12:23 Uhr

Möchte auch noch meinen Senf dazu abgeben.

Ich bin Zimmerergeselle, keine Matura und noch weniger Studium aber mittlerweile mehr als 10 Jahre Erfahrung (beginnend mit einer Umschulung durch das AMS)

Ich bin ein wie von meinen Vorrednern beschriebener Codemonkey. Dafür einer der schnellsten und sichersten in der Firma (25 Programmierer). Auch schneller/besser als Studierte.

Spezifikation zu schreiben bekomme ich aber nicht, einerseits da ich es nicht wirklich gut kann, keine Erfahrung. Andererseits da sie in Englisch geschrieben werden müssen und meines ist ... far from perfect. Und es der Firma offensichtlich zu viel Aufwand ist dass ich mir diese Erfahrung aneignen könnte.

Bin meines Zeichens SeniorDeveloper (steht auf der Visitenkarte) in einem Kundenteam und bilde auch neue Mitarbeiter aus. Bin MergeMaster (interner Titel), und werde geholt wenn es irgendwo brennt.

Fazit:
in kleineren Firmen macht es "keinen" Unterschied ob man studiert hat oder nicht. da sowieso zuwenig da sind um die Aufgaben strikt verteilen zu können.
Aber in grösseren Firmen (aktueller) ist man als nicht studierter bald mal programmierer 2. Klasse. Unabhängig der tatsächlichen Qualifikation. Die Specs der anderen sind auch nicht der Bringer.
Verdienstmässig kann ich aber mit den Studierten mithalten, wenn ich nicht sogar besser dastehe.

Und als einer der gelgentlich Lebensläufe durcharbeiten muss:
Was ich bei den Studierten als Gefahr sehe: er kann das Studium zwar erfolgreich abgeschlossen haben, hats aber nur gemacht weil er nicht wusste was er sonst tun hätte sollen. Und dann hat man einen relativ teueren eingebildeten Noob da sitzen (passierte nicht nur einmal).
das kann man bei einem Quereinsteiger fast ausschliessen, man tut sich das Umsteigen nicht an wenn man es nicht wirklich will. Und die sind definitiv bemühter und interessierter (nicht jeder, aber im allgemeinen kann ich das schon so sagn)

Und wenn man beim Bewerbungsgespräch von privaten Projekte erzählen kann und ev. eine Lauffähige Demo machen kann zieht das schon gewaltig, dieser ist zwar auf der theoretischen Ebene nicht so der Bringer. (Mich hat man beim Bewerbungsgespräch gefragt welche Normalform ich in der Datenbank verwende, und ich antwortete "im Normalfall Access")
Aber mit einer lauffähige Multithreading Anwendung mit einem Progressbar in der ComboBox (fürs Laden von Daten) konnte ich mich gegen 60 andere Bewerber durchsetzen.

20.07.2011 - 22:00 Uhr

@Ahrimaan
Alleine wenn jemand bei Patterns 'immer' sagt stelle ich es in Frage.
Es ist richtig gegen interfaces zu programmieren hat definitv einen Sinn, allerdings kenne ich auch das Gegenteil. Bei uns in der Firma programmieren wir gegen soviele Interfaces (weil dann können wir alles austauschen und customizen) dass sich keiner mehr auskennt was eigentlich abgeht und das erste Interface, bzw die Klasse dazu sieht noch immer gleich aus wie vor drei Jahren wie ich es programmiert habe, also nix mit austauschen. Und einen haben wir, der implementier ein Interface wenn es techniss einen Sinn ergibt, und ich kann Dir sagen niemand versteht seinen Code.

@gfoidl
Das SRP ist mir im Grund klar und ich gehe auch darauf ein wenn ich etwas entwickle. Allerdings mache ich in diesem Bereich wegen der Lesbarkeit und wartbarkeit Abstriche. eine ProcessModificationIdentifier hinter einem Interface mit IOC und DI bereitstellen ist schwieriger zu entziffern als
ProcessModificationIdentifier identifier = new ProcessModiificationIdentifier();
(da drin ist die Guid), ein klick go to definition und ich sehe die Klasse, sonst muss ich das interface suche und dann kucken wer das alles implementiert.
Ich verstehe das Prinzip, aber wenn es das Verständnis des Codes erschwert gehe ich gerne Kompromisse ein.

Und an Dich geht auch die Medailie fürs helfen, und ich bekomme wiedereinmal die Goldene Ananas. Offensichtlich habe ich beim herumprobieren in den letzten 3 Wochen irgendwas kaputt gemacht, jetzt habe ich es nun gerichtet. Jetzt kommt was falsches aber es wird wenigstens aufgerufen.

@Sarc
Du hast auch in die richtige Kerbe geschlagen.

20.07.2011 - 12:57 Uhr

Ich hab das Retrun umgebaut, jetzt wird sie garnicht mehr aufgerufen !?!
Finde ich jetzt aber auch schräg.
Generell hatte ich aber das Problem dass EqualsProcessModificationArgument nicht aufgerufen wird.

Ist ein gutes Design, einen privat Spass einer Klasse auslagern nur zum testen?
Hmm widerstrebt mir irgendwie, vorallem da es ja zum Mocken gehen sollte

// EDIT:
gerade gefunden in Moq.Mock<T> - how to setup a method that takes an expression:

However you are coming up against one of Moq's shortcomings. You would want to put an actual expression there instead of using It.IsAny, but Moq doesn't support setting up methods that take expressions with specific expressions (it's a difficult feature to implement). The difficulty comes from having to figure out whether two expressions are equivalent.

Heist das, das geht nicht?

20.07.2011 - 12:35 Uhr

@gfoidl
Ja, ich denke Du hast mich richtig verstanden, allerdings probiere ich schon ewig damit herum und schaffe es nicht um die Burg.
Die Haltepunkte die ich da setzte werden nicht mal angesprungen. Also wenn etwas falsches geliefert werden würde wäre es ja noch ok, aber es wird nicht mal was aufgerufen.

Hier ein OriginalCode (nicht aufbereitet) der den Callback nicht aufruft:

mObjectStoreServerMock.Setup(mock => mock.ProcessModification(
It.IsAny<ProcessModificationArgument>()))
.Callback<ProcessModificationArgument>(argument => EqualsProcessModificationArgument(argument, processModificationEventArgs)
).Returns(TestResults.LoadProcessModificationResult(processModificationEventArgs));

@zoomi
war ein Fehler im Aufbereiten, habs schon ausgebessert.

Generell wollte ich sowas vermeiden, nur wegen dem Testen ein neues Interface einführen. (Oder ProcessIdentifierFactory (liefert die Guid))
Vorallem da das Ding das fast public sein müsste damit ich auch von den Tests darauf zugreifen müsste. Und das schmeckt mir dann garnicht.

20.07.2011 - 11:28 Uhr

Hallo Ihr,

Ich glaube es heist Weakmatching, Ich möchte das Parameter nur teilweise Matchen.

Ich habe eine Klasse die als Identifier einen Guid erstellt.
Guid ProcessArguments.Identifier;
Diese Klasse hat auch noch eine zweite Property
List<string> ProcessArguments.Strings

In meiner TestKlasse bereichte ich eine Instance auf um sie der Method Setup des Moq frameworks

ProcessArgument arg = new ProcessArgument();
// der Identifier wird im ctor zugewiesen (eine Guid erstellt)
arg.Strings.Add("test");

Die Methode die ich testen möchte erstellt ebenfalls ein ProcessArgument,
klarerweise mit einer anderen Guid.

Wie kann ich nun das Moq framework aufsetzten dass nur die Gleichheit der Property Strings überprüft wird?

Ich verbringe leider schon realtive viel Zeit damit, wäre net wenn Ihr mir dabei helfen könntet!?

mbg
Robert Rossegger

Noch ein bisschen Code, zum zeigen was ich habe, aber leider nicht funktioniert.

mTestClassMock.Setup(mock => mock.MethodToTest(It.Is<ProcessArgument>(argument => EqualsProcessArgument(argument, processModificationEventArgs))
)).Returns(bla));


private static bool EqualsProcessArgument(ProcessArgument processModificationArgument, ProcessArgument processModificationArgumento)
{
// wird nie aufgerufen!
  return true;
}

http://code.google.com/p/moq/wiki/QuickStart
diese seite sah für mich am richtigsten aus, allerdings habe ich nicht mal annähernd das gleiche Verhalten.

Moq Version:
4.0.10827.0

// Edit Fehler behoben, danke fürs genaue lesen

13.07.2011 - 18:30 Uhr

aso
Ich hatte am Server immer das ganze Programm und das UpdateProgramm hat einfach alle Files durchgesehen welches neuer ist.
allerdings hatte ich keine Kontrolle darüber was in welcher Version erneuert wurde.

13.07.2011 - 14:01 Uhr

Beim durchlesen drängt sich mir eine Frage auf
Wer soll wann entscheiden, welche Version er runterladet
1.04 oder die neuere 1.05?

07.07.2011 - 16:28 Uhr

oh, kann sein dass ich gesucht habe bevor es diese gegeben hat 😉
na egal, jetzt schreibe ich schon einen eigenen

07.07.2011 - 13:28 Uhr

You Ain´t Gonna Need It (YAGNI)

wenn man alles implementiert was man irgendwann vielleich mal benötigt, würde man nie fertig werden.
Klar wenn man nen Logger austauscht hat man dann irgendwann vielleicht mehr arbeit.
Aber wenn man sich an diese Regel hält erspart man sich in summe soviel Zeit, dass sich das widerum locker ausgeht.
Wenn ich diese Regel nicht beachten würde, würde ich noch immer am ORMapper programmieren und nicht den SmartClientLayer.
Aber Vorsicht, sich darüber Gedanken zu machen hat keiner verboten, also nicht unötig den Weg verbauen.

07.07.2011 - 10:27 Uhr

Ich habe keinen gefunden der ähnlich Gentle ist, aber ich bin gerade dabei einen zu programmieren.
Meinen Recherchen nach nehmen die meinste ORM NHiberNate als Vorbild
Zuminstest habe ich noch nicht sehr viele Attributgetriebene ORM gefunden.

07.07.2011 - 09:37 Uhr

Wir in der Firma haben einen 'Wrapper' um Log4Net herum gebaut
Ähnlich wie von FZelle beschrieben.
Allerdings haben wir festgestellt, dass wir mit an Sicherheit grenzender Wahrscheinlichkeit den Logger nie austauschen werden und diesen Gedanken würde ich Dir auch ans Herz legen.
Tauscht man wirklich einen Logger so oft aus, dass man einen Wrapper benötigt?

05.07.2011 - 13:27 Uhr

jettzt hab ichs verstanden,
entweder Code generieren, oder einen code schreiben der ein File interpretieren kann und zur Laufzeit ein Form erzeugt.
aber für meinen Geschmak würde ich ein designer file generieren,eben damit
VS auch was damit anfangen kann. Würd ich halt meinen.
aber ich hab schon festgestellt dass ich "manchmal" eigenartige Ansichten habe 😉

05.07.2011 - 09:35 Uhr

aso, ok da sehe ich warhscheinlich nur im Detail Unterschiede.
Ich muss in beiden Fällen Code generieren, und dieser erzeugt dann eine Form.
ob der generierte Code in einem File mit der Endung .cs liegt oder .Designer.cs sehe ich wie gesagt nur im Detail Unterschiede, der Code selbst wird ja ähnlich, wenn nicht gleich aussehen.
Da würde ich sogar eher noch bei .Designer.cs bleiben, da das VS auch mit dem generierten code umgehen kann.

05.07.2011 - 08:25 Uhr

FZelle:
Die Frage verstehe ich nicht, ist das Designer file nicht die Form

20.06.2011 - 23:02 Uhr

Ich persönlich empfinde Win2000 als eines der gelungenstens Betriebssystem von Microsoft.
Bin sehr lange damit gefahren, erst mit einem neuen Laptop bin ich auf XP umgestiegen.

Und von der Geschwindigkeit her konnte ich mich ne beschweren. ist wie bei allen Betriebssystem. Hast Du das doppelte als empfohlen ist alles schnell.
win7 auf einem Notebook mit 2 GB Ram ist sicher langsamer als ein Win7 auf meinem Notebook mit 8 GB und einer SSD.

Und wenn auf dem Win2000 alles läuft was ich zum Arbeiten brauche und das in einer annehmbaren Geschwindigkeit würde ich selbst heute noch keinen Grund sehen umzusteigen. (Auch wenn mir Win7 sehr gefällt)

Es ist einfach ein Aufwand der sich nie, oder sehr spät lohnt.

Ich persönlich verwende Office 2003 und sehe absolut keinen Grund auf eine neuere Version umzusteigen.
Da kenne ich schon alle Menüpunkte und meine Accessdatenbank geht auch auf.
Ja, neuere Versionen sind bunter, aber he, ich bin Programmierer von mir aus könnte die Welt in Schwarz weis sein. Naja, ein paar rothaarige dürfte es schon geben 😉

17.06.2011 - 13:42 Uhr

Ich hab sowas mal im CustomDrawCell Event gemacht.
war von der Performance nicht so schrecklich. wenn man sich nur auf bereits geladene Daten bescchränkt ist sollten sich die Performance einbussen in Grenzen halten.

07.06.2011 - 10:49 Uhr

Ich habe mich im grossen und ganzen gegen "schlechtes Design" gewehrt, so pauschal kann man das nicht einfach sagen. Ich stimme aber der Aussage zu, dass es immer ein besseres Design gibt.

Das erklärt einiges zur Wirtschaftslage 😄 - SCNR (nicht böse gemeint) -

erwischt, ja, ich wars 😉

07.06.2011 - 10:18 Uhr

klingt für mich nach schlechtem und benutzerunfreundlichem Design. Ich möchte als Benutzer bestimmen, was ich wann tun möchte und nicht von einem Programm vorgegeben bekommen, was ich in welcher Reihenfolge zu tun habe.

...

Und sage bitte nicht, es würde nicht anders gehen.){gray}

Hallo herbivore,

ich habe das schon sehr oft von dir gelesen, soweit kann ich Deine Argumentation auch verstehen da man ja mit den "neuen" Programmier-Möglichkeiten auch "neue" Programm-Möglichkeiten erhält welche man auch nutzen soll.

Aber gleich von schlechten Design zu reden halte ich für vorschnell, vorallem, da Du nicht weist von wem die Idee kam (Kunde?) bzw. was das Fenster eigentlich anzeigt.

Wenn ich Deine Vorstellungen richtig verstehe (wenn ich hier falsch liege ist der ganze Beitrag obsolete), stellst Du Dir eine moderne Anwendung so vor dass alle Meldungen als eigene Tabs in einer "MDI" erscheinen und er Benutzer sich aussuchen kann ob er sich jetzt darum annimmt ... oder auch nicht.

Nur es gibt manche Workflows im Tagesablauf eines Benutzers die die ganze Anwendung blocken kann.
Ich schreibe Börsendatenimportsystem für Grossbanken. Und wenn da ein User eine Aktie bearbeitet (die Informationen dazu) und er beim Eingeben der Daten einen Fehler macht, dann hat er sich zum Kuckuck sofort darum zu kümmern warum z.b. die Validierung der Preise fehlschlägt. Er hat ein Lock auf die Aktie und jeder andere Teil des Systems steht. Es kann ja nicht exportiert werden wenn es gerade bearbeitet wird. Dann steht eine 64 Core Maschine und wartet bis der liebe User sich entscheidet die Fehler zu bearbeiten. Nö das geht einfach nicht. Da muss der ValidationErrorDialog aufpoppen und er hat das JETZT zu machen.

Was ich damit sagen will, nur weil ein blocking Dialog aufpoppt es noch lange kein schlechtes Design ist.

06.06.2011 - 14:09 Uhr

wenn Du die Patterns schon kennst, bin ich ganz Deiner Meinung
Wenn Du gerade mit Patterns anfängst wirst Du noch nicht das Auge dafür haben.
so wollte ich es ausdrücken

06.06.2011 - 13:34 Uhr

Ich habe mir sehr schwer getan beim Lernen der Patterns (hab natürlich noch nicht alle drauf)
Aber ich denke der beste Weg könnte sein, einfach mal im Internet nach Patterns suchen und alles lesen was man findet, hier im Forum wurde natürlich auch schon viel darüber gesprochen und wenn man den vorhanden Links folgt ist man schon mal ein paar Wochen beschäftigt.
Verstehen der Patterns ist imho nur durchs lesen nicht möglich, denn sie lösen Probleme die man nicht hat.
Wenn man ein schönes Stück Zeit investiert hat, dann sollte man anfangen zu programmieren ohne sonderlich auf die Patterns zu achten. Wenn man ein Modul fertig hat, damit meine ich nicht eine einzelne Klasse sondern eher was in Richtung einem Framework, also wenn man ein Modul fertig hat, nochmal über den ganzen Code reflektieren.
Das kann (soll) ruhig solange dauern wie das Schreiben selbst, da wirst Du selbst an gewissen Stellen denken, "Moment, dass könnte man besser machen" dann das Pattern suchen und mit besten wissen und Gewissen den bestehenden Code umbauen.
Das kann (soll) ruhig solange dauern wie das Schreiben selbst, aber beim nächsten Modul sitzt das Pattern schon fest in Deinem Hirn und Du machst es von Anfang an richtig.
Das eine Pattern oder zwei.
Ich selbst halte es für unmöglich, nach dem Lesen von einem Buch alle Patterns richtig anwenden zu können. Also immer schön Step by Step aber dafür sitzt das was man gelernt hat. Wichtig ist hierbei das man sich beim reflektieren genug Zeit lässt und diese Zeit auch nur fürs reflektieren vornimmt.

Soweit die Lesung aus meinem Kopf

06.06.2011 - 12:22 Uhr

jep, BeginInvoke wird wahrscheinlich die Methode Deiner Wahl sein

06.06.2011 - 11:25 Uhr

Du könntest die Property "ShowInTaskbar" probieren.

06.06.2011 - 11:24 Uhr

Was sollte der Thread machen, während der Dialog offen ist?

// EDIT
Wie sagt der Thread der GUI das was angezeigt werden soll? (Code)

06.06.2011 - 10:53 Uhr

Klingt irgendwie wie ein interessantes Anwendungsgebiet für MDI?

06.06.2011 - 10:50 Uhr

grundsätzlich ja, wartet er auf eine Antwort vom Gui Thread? (Antwort vom User)

01.06.2011 - 09:24 Uhr

anders gefragt:
Welchen Vorteil erwartest Du Dir davon wenn das DomainModel bei jedem ->Programmstart<- neu generiert wird?

31.05.2011 - 17:49 Uhr

generell denke ich, dass dieser Schritt nicht automatisch erfolgen sollte.
Klar könnte man es automatisieren und es würde auch nichts schlimmes passieren ... meistens.
Und genau dieses sagt mir, es muss ein ganz bewusster Vorgang sein, sein DomänenModel zu generieren.
Es kommt eine Spalte weg, die wird aus dem EF raus'generiert' und die Anwendung verabschiedet sich ... bei einem User/Programmierer der nichts mit dem DomänenModel zu tun hat und der suchst sich dann zum Idioten bis er herausgefunden hat was da eigentlich los ist.

31.05.2011 - 11:25 Uhr

sobald ich Marshal... lese denke ich, verlässt man die .Net Bordmittel


      string fileName = @"Some place on your Harddisk.";

      StructForSerialization structForSerialization = new StructForSerialization();
      structForSerialization.IntMember = 3;
      structForSerialization.StringMember = "Some Text";

      SaveGraph(fileName, structForSerialization);

      StructForSerialization loadedStruct = LoadGraph(fileName);

      if (structForSerialization.Equals(loadedStruct))
        MessageBox.Show("There is all fine.");
      else
        MessageBox.Show("There is something wrong.");

    private static StructForSerialization LoadGraph(string fileName)
    {
      if (!File.Exists(fileName))
        throw new ArgumentException("fileName doesn't exist.");

      using (FileStream stream = new FileStream(fileName, FileMode.Open))
      {
        BinaryFormatter formatter = new BinaryFormatter();
        return (StructForSerialization)formatter.Deserialize(stream);
      }
    }

    private static void SaveGraph(string fileName, StructForSerialization structForSerialization)
    {
      if (File.Exists(fileName))
        File.Delete(fileName);

      using (FileStream stream = new FileStream(fileName, FileMode.CreateNew))
      {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, structForSerialization);

        stream.Flush();
      }
    }
  }

  [Serializable]
  public struct StructForSerialization
  {

    private string mStringMember;
    private int mIntMember;

    public string StringMember
    {
      get { return mStringMember; }
      set { mStringMember = value; }
    }

    public int IntMember
    {
      get { return mIntMember; }
      set { mIntMember = value; }
    }

    public override bool Equals(object obj)
    {
      if (!(obj is StructForSerialization))
        return false;

      StructForSerialization otherObj = (StructForSerialization)obj;

      return mStringMember.Equals(otherObj.mStringMember) && mIntMember.Equals(otherObj.mIntMember);
    }

  }
31.05.2011 - 11:02 Uhr

Du könntest die Sache dadurch auch relativ generisch halten,
Wenn der Datensatz aus einer anderen Tabelle kommt, kannst Du ein anderes control links und rechts anzeigen.

und wenn du einen brauchbaren monitor hast (> 21") dann ist das auch noch ne tolle und übersichtliche Ansicht.

31.05.2011 - 10:16 Uhr

ganz habe ich es noch immer nicht verstanden, aber generell würde ich mich da mal von diesem DataGrid verabschieden.
Wenn Du vorher/nachher vergleichen musst würde ich bei der Anzeige eher auf etwas WinMerge ähnliches wechseln.

Links und rechts die TextBoxen oder MemoEdits die benötigt werden um den Datensatz anzuzeigen und in der mitte ein kleines DataGrid indem nur das Datum und wer es geändert hat steht.

MemoEdits und TextEdits sind sicher schneller in der Anzeige und ein MemoEdit eignet sich sicher besser um einen grossen Inhalt anzuzeigen als eine popplige DataGrid Zelle.

die Idee mit dem Listview würde ich gleich wieder vergessen, das Ding eignet sich sicher nicht dafür.

30.05.2011 - 15:51 Uhr

Wie zeigst Du die Datensätze an?

Um welchen Vergleich geht es da? eine Art Merge?

Welche Datensätze werden verglichen? Die gleichen, nur ne andere Version?

Nur so ein Vorschlag:
Könnte man die Anzeige so umbauen, dass das Grid in der Mitte ist und links und rechts davon ein/mehrere MemoEdit in denen die Inhalte dieser Felder angezeigt wird?

30.05.2011 - 13:34 Uhr

Da wird Dir wahrscheinlich nur ein Profiler helfen können der Dir aufzeigt welcher Code beim Spaltegrösse anpassen ausgeführt wird.
(JetBrainsDotTrace ist das Programm meiner Wahl, gibts auch ne Demoversion)

D.h. den Code finden der ausgeführt wird, dann weist Du auch was es so langsam macht

28.05.2011 - 18:39 Uhr

Ich hatte früher sehr grosse Schwankungen der Motivation
Manchmal konnte ich vom PC nicht weg, programmieren bis die Sonne aufgeht
und dann wieder 2 Wochen nicht mal reingeschaut.
was natürlich auch dazu führt, dass man nach 2 Wochen eigentlich nicht mehr weis wo man war.

Aber seitdem ich privat auf TDD umgestellt habe sind diese Schwankungen weg
(ich nenne es TDD, ob es das wirklich ist kann ich nicht sagen, ich schreibe halt zuerst einen Test)

Da sich dadurch die Herangehensweise an das Problem ändert bekommt man auch einen anderen Blick auf 'Wo stehe ich gerade'

Früher programmierte ich oft 3 Wochen an einer Funktion (4-5 h die Woche, mehr geht nicht) und dann, wenn ich fertig war, wusste ich nicht mehr für was ich die eigentlich geschrieben hatte und/oder ich wusste nicht mehr was ich eigentlich vor hatte.

mit TDD ist es eigentlich von Haus aus dokumentiert wo man steht

zuerst macht man (mache ich) UseCases: Was brauche ich eigentlich?
Da wachsen dann wenige Klassen heraus die für z.b. das neue Framework öffentlich benützbar sein müssen und welche Methoden sie haben müssen
Daraus erstelle ich ein UML und mache mir das erste Mal darüber Gedanken was das Ding intern eigentlich alles können muss (UseCases anpassen erlaubt ... sollte aber im Rahmen bleiben)
Danach erstelle ich aus dem UML die benötigten Klassen (hier sieht man das erste Mal auch die internen)
Dann baue ich die UseCases um zu TestMethoden in UnitTest-manier

Und als Abschluss mache ich jeden Test grün.

Mit dieser Vorgehensweise kann man am Abend sagen, heute habe ich 3 Tests grün gemacht. Egal wieviele noch sind, jetzt sind es 3 weniger und so bleibt die Motivation fast immer auf dem gleichen Level.

Fazit:
Mit einer anderen Vorgehensweise kann man die, in meinem Fall, die fehlende Planung und die dadurch Schwankende Motivation gut unter Kontrolle bringen.

26.04.2011 - 14:21 Uhr

Kann sein dass ich jetzt daneben liege, aber:

Speichere den ConnectionString mit einem {0} für das Passwort
und wenn Du den connectionString zuweise schreibe
string.Format(connectionString, passwort)

dann wird das {0} durch den Inhalt der variable passwort ersetzt.

31.03.2011 - 10:11 Uhr

Das klingt sehr eigenartig, entweder hast Du einen 486er oder da wird irgendwo noch ein zusätzlicher Code ausgeführt.

Schon mal was mit einem Profiler gemacht?
Ich verwende JetBrains dotTrace, denke sollte auch eine Trial davon geben
Der zeigt Dir recht lässig an, welcher Code ausgeführt wird und wie lange er wo braucht.
Schon einige Sachen gefunden, vorallem in der Nähe der GUI.

30.03.2011 - 09:34 Uhr

Ich kenne Deinen Code nicht, aber ich würde mir erwarten diesen oder ähnlichen Code zu finden:


{
  string searchedValue = "My Name"; // 1

  BoundElement boundElement = new BoundElement("My Name", 32); // 2

  bool matchReflection = FilterElement(boundElement, "Name", searchedValue); //3
}

public bool FilterElement(BoundElement element, string propertyName, object searchedValue)
{
  PropertyInfo propertyInfo = element.GetType().GetProperty(propertyName); // 4
  object propertyValue = propertyInfo.GetValue(element, null);
  return object.Equals(propertyValue, searchedValue);
}

1: Der Kern ist, irgendwo wird definiert nach was gesucht werden soll
2: Irgendwo wird ein Element erzeugt das gegen die Liste gebunden ist ( T )
3: irgendwo wird die Suche angestossen wo definiert wird welche Property durchsucht werden soll
4: irgendwo wird mittels Reflection der Wert der Property des gebundenen elements ausgelesen.

Die Reflection ist langsam, ich hab mal den Satz fallen lassen:
"Man kennt sich dann mit Reflection aus, wenn man versucht sie zu vermeiden."

wie vermeidet man die Reflection in diesem Fall:

{
  string searchedValue = "My Name";

  BoundElement boundElement = new BoundElement("My Name", 32);
  Func<BoundElement, bool> filterFunc = new Func<BoundElement, bool>((element) =>
    {
      return element.Name == searchedValue;
    });

  bool matchFunc = FilterElement(boundElement, filterFunc);
}

public bool FilterElement(BoundElement element, Func<BoundElement, bool> filterFunc)
{
  return filterFunc(element);
}

an der Stelle in der festgelegt wird welche Property durchsucht werden soll, erstellt man eine Func wie oben und gibt diese statt dem PropertyNamen weiter.
Und weg ist die Reflection.
es wird dadurch nicht wirklich leichter zu verstehen und zu debuggen, aber der Performance Gewinn sollte das aufwiegen. bzw. wenn man damit mehr Erfahrung hat sind die Nachteile auch verschwunden (Das erste Mal debuggen von so einer Struktur hat ein paar Fragezeichen auf meine Stirn gebrannt)

    public class BoundElement
    {

      private string mName;
      private int mAge;

      public BoundElement(string name, int age)
      {
        mName = name;
        mAge = age;
      }

      public string Name
      {
        get { return mName; }
      }

      public int Age
      {
        get { return mAge; }
      }

    }
14.03.2011 - 16:04 Uhr

Ist mir da ein Beitrag ausgekommen, herzlichen Dank für den Link.
Denke jetzt habe ich es kapiert und kann es einsetzen.

🔝

14.03.2011 - 13:15 Uhr

aahhh ...

Di-Container ist das Object das man braucht um IoC zu "erhalten".
Also sowas ähnliches wie mein Objekt mit dem Namen IoCServiceLocator.

Aber so wie Du es geschrieben hast, gibt es zwischen dem DI-Container und dem IoCServiceLocator einen Unterschied?
Kannst Du da eventuell noch einen Satz dazu loswerden?

14.03.2011 - 10:39 Uhr

Grüss euch,

ich habe mir nun den ganzen Thread und alle verlinkten Seiten zur Gänze durchgelesen wie auch generell im Internet gestöbert.

Fazit:
IoC:


<component 
  id="internalname" 
  service="oRRoSoft.InterfaceWhichIsImplemented, oRRoSoft" 
  type="oRRoSoft.TypeWhichShouldBeResolved, oRRoSoft" />

ergibt:

IoCServiceLocator.Resolve<InterfaceWhichIsImplemented>();

DI besteht im eigentlichen Sinne nur aus einem ctor:

public DITestClass(IExternalDependency externalDependency) { /* code */ }

woher die Klasse die Instanze bekommt ist dem DI Prinzip egal.

Die Kombination draus wäre:

<component 
  id="dependecy" 
  service="oRRoSoft.IExternalDependency, oRRoSoft" 
  type="oRRoSoft.ExternalDependency, oRRoSoft" />
<component 
  id="internalname" 
  service="oRRoSoft.InterfaceWhichIsImplemented, oRRoSoft" 
  type="oRRoSoft.TypeWhichShouldBeResolved, oRRoSoft">
  <parameters>
    <externalDependency>${dependency}<externalDependency/>
  </parameters>
</component>

ergibt:

IoCServiceLocator.Resolve<InterfaceWhichIsImplemented>();

und die instanzierte Klasse bekommt vom IoC den fehlenden Parameter injected

Soweit habe ich es verstanden und ich glaube damit sind alle Fälle abgedeckt die man so im täglichen Leben braucht.

Und nun die Frage, für was brauche ich dann einen DI-Container?
Ich lese immer wieder von ihm, aber nirgends finde ich eine Erklärung wie das Ding aussieht oder was es eigentlich tut.
Habe ich mich irgendwo in der Begriffeflut verirrt oder verstehe ich nicht was es ist?

10.03.2011 - 11:42 Uhr

Irgendwie wäre aber interessant herauszufinden warum das ding nicht dabei ist

Wenn du das Attribute weg lässt, macht er Dir dann einen Node?

sie Dir mal die Attribute
OnSerialized und OnDeserialized an, vielleicht kannst Du aus den contexten was rauslesen.

01.03.2011 - 12:59 Uhr

Wie serialisiert Du?
Bisschen Code könnte da helfen

23.02.2011 - 18:07 Uhr

Ich habe mir nun ein bisschen mehr Zeit genommen und die Hilfe durchgegrast, jetzt weis ich ein bisschen mehr darüber.

Ein Rollback ist nicht zwingend erforderlich, richtig, aber vom Feeling her würde es gut rein passen.

Das ich die Transaction an einen Server schicken kann gefällt mir gut, hab dazu zwar (noch) keinen Use-Case, aber das Feature würde mir fehlen.

Ich habe in meinem Client kein ADO.Net laufen. Der client (die Anwendung) kennt nur den ObjectStoreClient der widerum mit dem ObjectStoreService spricht und dieser mit einem IConnector welcher dann die wirkliche Datenbank kennt (In diesem Fall eben unbekannt).

D.h. das die Transaction (TransactionScope) mehrere ADO.Net Connections verwalten kann ist gut, ich habe aber keine.
Das ich nach Commit() den ObjectStoreClient aufrufen muss ... dass ist ja genau das ich vermeiden will. Ich möchte den User (Programmierer) von diesen Dingen fern halten. Ich habe die Erfahung damit dass das nicht gut geht.

Die Validierung ist ja grundsätzlich mal auf dem BusinessObject drauf, aber manche Kunden wollen halt mehr, oder eine inteligentere Validierung die ich nicht auf dem DTO (BusinessObject) unterbringe und für das brauche ich das Commiting event um den Speichervorgang nicht zu zulassen wenn was fehlt.

danke für die Anregungen, hab wieder was gelernt, aber einerseits kann es mir zuviel, eben irgendwelche Objekte in die Transaction aufnehmen, ich brauche nur BusinessObjects, andererseits zuwenig, eben ein fehlendes Rollback und die Events wie auch den ObjectStoreClient muss ich selbst anzapfen, was ich genau mit dem Transaction-Framework vermeiden will.

18.02.2011 - 11:21 Uhr

Hallo Rainbird

ich habe mir dazu ein bisschen die Hilfe durchgelesen.
Hmm...
Scheint mir nicht ganz das zu sein was ich brauche.
Kann sein dass ich das auf die schnelle nicht gefunden habe (bin ja in der Arbeit)
aber mir fehlt die Rollback Methode.
auch fehlen mir Events (Commiting -> für eine Validierung, Commited -> weis ich noch nicht für was, Rolledback ->weis ich auch noch nicht)
und bei einem Commit muss ich über ein Interface zur ObjectStoreService, das werd ich dem TransactionScope auch nicht beibringen können.

So können alle Methoden in der Aufrufkette ganz leicht an der Transaktion teilnehmen (wenn sie möchten). Das Blöde daran ist, die die daran teilnehmen sollen, wissen nicht dass sie daran teilnehmen wollen. Momentan ist es so gelöst dass das BusinessObject nicht weis dass es Transactions gibt.

using (Transaction transaction = TransactionPool.CreateTransaction(threadwideTransaction = true, egal = false))
{
  Addresse addresse = new Addresse();
  Assert.IsTrue(transaction.PendingTransaction.Count == 1);
  //
}

Bitte fragt nicht wie ich das gelöst habe.

Einerseits ist ja mein Ziel nicht eine Transaction für jeden und alles zu bauen, da lasse ich die Leute ran die das besser können.
Ich schreibe "nur" einen SmartClientLayer und die Transation die ich hier brauche ist nur für Datenbankobjekte (BusinessObjects) gedacht.

Aber danke für den Hinweis, ich kannte noch nicht mal den Namespace.

//Edit: schöner gemacht
PS: Du kommst aber auch aus einer schönen Gegend

17.02.2011 - 13:38 Uhr

Nein war es nicht, die anderen Dinge habe ich gleich oder ähnlich angedacht.
vielleicht ein paar implementierungs details anders, aber im grossen und ganzen bin ich nicht weit daneben, denke ich mir.

keine Probleme damit, das gefällt mir.

ein Rollback auf einer ChildTransaction (BusinessObjectTransaction oder Transaction)
wirft alle Änderungen weg, egal ob es einen Parent gibt oder nicht, d.h. falls ein Parent vorhanden ist, bekommt der nur mit das ein Child "gestorben" ist (die genaue implementierung ist noch nicht überlegt, wie gesagt erst die Usecases und ein paar Tests auf dem TransactionPool fertig)

Das ist ein gutes Argument
Mein Ziel ist eine Advanced Kiddy Programming framework für Transactions.
Kiddy im Sinne von, man braucht nicht tage lang Hilfe dokumente lesen bis man versteht um was es geht
Mit Advanced meine ich dass man generell wissen sollte was man tut.
und bei Threads wusste ich selbst noch nicht wo ich das hingeben sollte (vorallem weil ja noch ein, zwei andere Probleme damit auftauchen) aber so wie Du es schreibst fällt es für mich in Advanced, d.h. ich brauche mich nicht sonderlich darum kümmern.

Besten dank fürs Gespräch!

17.02.2011 - 12:54 Uhr

So habe mir mal die Dinge durchgelesen
aber das Teil von Ralf's Sudelbücher geht einerseits über mein Verständniss, andererseits auch über meine Anforderungen (soviel habe ich verstanden 😃 )

Ich brauche Transactionhandling nur auf BusinessObject, genauer ITransactionableObjects. Ich kann 2 BusinessObjects in eine Transaction hängen und diese gemeinsam commiten, damit habe ich auch das Kontobewegungs problem gelöst, aber ein FileStream interessiert mich nicht.

Ja, wieder richtig in meinem Bespiel hat es keine Auswirkung auf den Ansprechpartner weil eh reverted wird, aber es geht mir um das implizite.

Hast Du kein Problem mit dem Impliztiten Commit auf ChildObjects?

Argument eines Kollegens:
Wenn ich das implizite erlaube, kann es, z.b. durch multithreading passieren dass ein Thread noch nicht fertig ist, während der erste (MainThread) schon mal die Globale Transaction Commited.
Funktioniert auch ohne fehler, und für den zweiten (Backgroundworker) wird eine neue Transaction erstellt, die aber stirbt sobald der Thread endet, bzw. im besten Fall ewig offen bleibt weil keiner weis dass sie existiert.

11.02.2011 - 15:03 Uhr

Ich glaube ich habe da eine Info unterschlagen:
die Property Ansprechpartner der Adresse ist eine List<Ansprechpartner>
(blödes Beispiel, da die Mehrzahl von Ansprechpartner ebenfalls Ansprechpartner ist)

Was mir aber auffällt, Du hast auf dem Ansprechpartner object kein Commit()
Das heist durch das adresse.Commit() wird ein implizites Commit auf die ChildObjects ausgeführt
(Ansprechpartner ist ein BusinessObject und somit ebenfalls "Commitable")
(in diesem Fall egal ob Ansprechpartner eine Liste ist oder nicht)

Genau das war aber der Punkt den meine Arbeitskollegen bekrittelten.

Mit den beiden Commit's hintereinander wird dir wahrscheinlich aufgefallen sein, dass es nested Transactions sind, die von einander abhängig sind.

ansprechpartner.Commit()
adresse.Rollback()

und keine Änderung ist in der Datenbank.
Ich glaube oracle kann sowas auch.

ist es da ok wenn da ein implizites commit auf den childs (childRelations) ausgeführt wird?

10.02.2011 - 23:30 Uhr

Hmm...

ich wollte eigentlich wissen wie man so ein TransactionFramework in der "realen Welt" benutzen möchte.

Der Hintergrund des Frameworks ist eigentlich schon "fertig"
zig UseCases sind ausgedacht und geschrieben, 3 oder 4 Testclassen sind geschrieben und die benötigten Klassen vom ClientLayer über den ObjectStoreService bis zur Datenbank (Connector) sind auch erstellt.

Es geht mir eigentlich nur um die Benutzung, dass ein Programmierer der das System nicht kennt es intuitiv benützen kann.

Adresse adresse = /*Load<Adresse>() aus der Datenbank*/
Ansprechpartner ansprechpartner = adresse.Ansprechpartner.Create(withParentTransaction = true);
ansprechpartner.Name = "Neuer Ansprechpartner";
ansprechpartner.Commit();
adresse.Commit();

ist das intuitiv?