Laden...

Forenbeiträge von GMLOD Ingesamt 1.200 Beiträge

25.12.2008 - 01:02 Uhr

Ich kann an deinem Code den Fehler nicht nachvollziehen. Das sollte so funktionieren.

Aber folgende Dinge sind mir aufgefallen:

            while (backgroundWorker1.IsBusy)
            {
                // Verarbeitung alle Windows-Meldungen, die sich derzeit in der Warteschlange sind.
                Application.DoEvents();
            }

Das Application.DoEvents() ist doch gar nicht notwendig! Der Backgroundworker blockiert die Nachrichtenverarbeitung doch eh nicht, da du ihn mit RunWorkerAsync aufgerufen hast! Diese Codezeilen sind unnötig und könnten auch für den Fehler verantwortlich sein. Vermutlich wird der Click Event nämlich nochmal ausgeführt, weil er noch nicht wirklich aus dem EventQueue entfernt wurde (Wahrscheinlich eine Race Condition).

 try
            {
                while (true)
                {
                    bw.Write(br.ReadByte());
                    //  Bytes zählen
                    counter++;
                    //  den Arbeitsfortschritt anzeigen
                    if (counter >= section)
                    {
                        worker.ReportProgress(++progress, summary);
                        counter = 0;
                    }

                    // Prüfen ob Cancel Button gedrückt wird.
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                    }
                }
            }
            catch
            {
            }
            finally
            {
                //  Alle Streams müssen geschlossen werden
                bw.Close();
                br.Close();
                fs.Close();
                hwrs.Close();
            }

Exception based Programming - böse, ganz böse. Tu das nicht. Eine Abbruchbedingung könnte man z.B. mit der Length-Eigenschaft eines Streams formulieren.

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                // Der User hat den vorgang abgebrochen
                MessageBox.Show("Operation was canceled");
            }
            else if (e.Error != null)
            {
                // Ein Fehler während des Downloads ist aufgetreten
                MessageBox.Show("Error during the download");
            }
            else
            {
                // Download beendet ohne fehler
                Close();
                Application.Restart();
            }

           // Enable den OK Button
            okButton.Enabled = true;

           // Disable den Cancel Button
            cancelButton.Enabled = false;
        }

Close() und Restart() machen doch überhaupt keinen Sinn! Warum würde man sowas tun wollen? Anschliessend auch noch die Buttons wieder enablen - das macht keinen Sinn. Du hast die Form doch eh schon zugemacht und den Prozess beendet und neugestartet. Warum?

25.12.2008 - 00:48 Uhr

Man braucht für einen Split nicht unbedingt einen char als Separator.

Natürlich kann man Split auch mit einem String[] füttern:


String toSplit = "Mein Name, der ist Thomas! Mein Name, ist Thomas.Mein Name ist Thomas.";

String[] splitter = new String[] { "Mein Name" };
String[] tokens = toSplit.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < tokens.Length; i++)
{
    MessageBox.Show(splitter[0] + tokens[i]);
}

Poste doch mal alle Variationen, die von so einem String vorkommen können. Dann lässt sich auch eine Regex dafür entwickeln.

25.12.2008 - 00:33 Uhr

Dieser Thread hat die ID 65536.

externe DLL importieren: 32bit und 64bit

Der 2^16 te Thread in diesem Forum, geposted an Weihnachten 😃

Zu deinem Problem:

Die Bitzahl des Systems kannst du folgendermaßen feststellen:

int bits = IntPtr.Size * 8;

Dies funktioniert, da es sich bei IntPtr um einen plattformabhängigen Zeiger handelt.

Wenn es sich um ein .NET Assembly handelt, das du laden willst, könntest du auch die Registry durchforsten um festzustellen, in welcher Variante das Framework vorliegt.

Für den Switch zwischen den DLLs gibt es mehrere Methoden.

Methode 1 - DLL beim Startup oder beim Deployment umbennen/kopieren

Stelle die Bitzahl fest und nenne die entsprechende DLL dann einfach testActive.dll. Importiere dann nur aus dieser DLL. Die anderen beiden DLLs könnte man dann löschen.

Vorteil: Einfach, wenig Code.
Nachteil: Man schleppt Müll mit sich rum, muss diesen, ähem, Schund bei jedem Start ausführen wenn man es nicht in den Deployment Prozess einbaut oder gar keinen will. Wenn man die überflüssigen DLLs löscht, kann man das Programm nicht mehr einfach zwischen zwei Architekturen kopieren. Desweiteren lässt sich die Komponente so nie gegen eine andere ersetzen.

Methode 2 - Benötigte Version zur Laufzeit feststellen

  1. Bau ein Interface, das alle Methoden zur Verfügung stellt, die du aus der DLL nutzen willst.
public interface IMyDll
{
    public void Method1();
    public void Method2();
}

  1. Baue dir 2 Klassen, die das Interface implementieren, eine für die 32 Bit Version und eine für die 64 Bit Version:

public class MyDllMethods32 : IMyDll
{

      /* snip */

     [DllImport(test_32.dll)]
     static extern void DllMethod();     

     public void Method1()
     {
          DllMethod();
     }

      /* snip */
}

public class MyDllMethods64 : IMyDll
{
     /* snip */

    [DllImport(test_64.dll)]
    static extern void DllMethod();

    public void Method1()
    {
       DllMethod();
    }

     /* snip */
}
  1. Stelle die Methoden zur Verfügung, z.B. als Singleton



public class DllMethods
{
      private static lockObject = new object();
      private static IMyDll _instance;
      
      /* snip */

      public static IMyDll Instance
      {
            get
            {
                lock(lockObject)
                {
                    if(_instance == null)
                    {
                        int bits = IntPtr.Size * 8;
                        if(bits == 32) _instance = new MyDllMethods32();
                        else if(bits == 64) _instance = new MyDllMethods64();
                    }
                }

                return _instance;
            }

           /* snip */
      }
}

Dann kannst du ganze einfach überall deine Methoden wie folgt verwenden:

DllMethods.Instance.Method1();

Vorteil: Flexibles Design, DLL Wechsel leicht möglich, erweiterbar.
Nachteil: Relativ aufwendig.

Methode 3 - Dll als in Memory Assembly nutzen

Stelle zur Laufzeit fest, welche Dll du brauchst. Lade diese mittels Assembly.Load einfach und greife dann mittels Reflection auf die enthaltenen Methoden zu.


/* snip */
//typen des assemblies feststellen
Type[] t = theLoadedAssembly.GetExportedTypes();

//methode aufrufen
MethodInfo mi = aTypeWithinTheDll.GetMethod("Method1");
mi.Invoke();
/* snip */

Vorteil: Relativ einfach
Nachteil: Funktioniert nicht mit nativem Code; Aufwendig - müsste auch wieder über ein schönes Interface (z.B. Facades) zur Verfügung gestellt werden. Unflexibel, man kann die Komponente nicht einfach tauschen.

Persönlich vertrete ich die Ansicht, dass, wenn du einen Installer haben willst - also eine Art Deploymentprozess - du dort die Abfrage machen solltest und dann einfach die richtige DLL mit entsprechendem Namen in das richtige Verzeichnis kopierst.

Planst du in naher Zukunft weitere DLLs hinzuzufügen, z.B. gegebenenfalls eine ganz andere Komponente für die gleiche Aufgabe zu nutzen, wärst du mit Methode 2 besser beraten, da du hierfür die Schnittstelle nicht ändern müsstest, sondern einfach eine weitere Klasse hinzufügst. Man kann damit auch zur Laufzeit sehr leicht die Dll wechseln.

Methode 3 macht Sinn, wenn du zur Laufzeit, aus was für Gründen auch immer, plötzlich dynamisch auf neue Methoden zugreifen willst. Schließlich genügt es hier einen Namen anzugeben. Diese Methodik würde sich auch sehr leicht über ein Config-File steuern lassen (das man z.B. beim Deploy anpassen könnte), aber genaugenommen eignet sie sich nur für Programme, die hochdynamisch sein müssen. Bei Methode 2 müsste man einen Code Generator dafür einsetzen, was erheblich aufwendiger wäre.

Was red ich hier eigentlich? Nimm einfach Methode 1.

22.12.2008 - 13:41 Uhr

Bist nicht der Einzige.

WIR SIND HELDEN! 😁

22.12.2008 - 10:08 Uhr

Hallo, Forenuser!

Da kommt man aus dem Urlaub und dann liegt da ein Angebot für eine MCSD Zertifizierung auf meinem Schreibtisch (wurde individuell vom Anbieter für mich erstellt).

So wie ich das sehe, ist das jedoch ein wenig outdated. Sollte man heutzutage noch den MCSD machen?

21.12.2008 - 23:20 Uhr

using System.Windows.Forms;
using System.Xml.Linq;
using System;
using System.IO; //hat gefehlt.

[assembly: Divine]

class DivineAttribute : Attribute
{
}

namespace ForumsProgramm
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine("Hello world?");

            if (haveApocalypse())
            {
                string s = "Bye, World!";
                //this.SaySomething(s);
                Program.SaySomething(s);
                MakePanic(s);
            }
        }

        static void SaySomething(string s)
        {
            MessageBox.Show(s, "Something very important to say");
        }
        
        static void MakePdelvosSigLookLikeProperEnglish(String replaceMakeWithDo)
        {
        }  
      
        static void CausePanic(string reason)
        //static void MakePanic(string reason)
        {
            int i2=100;
            for (int i = 0;i<i2;i++)
            {
                MessageBox.Show("Panic Reason:"+reason, "Incite Panic",MessageBoxButtons.OK);
            }

        }
        static bool haveApocalypse()
        {
            String SFile = Path.GetDirectoryName (System.Reflection.Assembly.GetExecutingAssembly().Location);
            SFile += "\\settings.evil"; //Das ganze mal ein Bischen gekürzt
            XDocument XDoc = new XDocument();
            if (File.Exists(SFile))
            {
                XDoc = XDocument.Load(SFile);
            }
            //return XDoc != null;
            return XDoc.Root != null;
        }
    }
}

21.12.2008 - 15:48 Uhr

Hier noch ein Screen.

Betreibe das ganze unter Windows XP Service Pack 2, XNA Game Studio Version 3.0, den neuesten NVidia Treibern und einer Auflösung von 1920x1200;

21.12.2008 - 15:37 Uhr

Wenn ich eine neue Map zum Projekt hinzufüge, kann ich diese nicht auswählen. Irgendwann switched es dann auf die neue Gridsize, das ist aber absolut nicht reproduzierbar für mich bisher. Ich kann jedenfalls nicht mehrere Maps im Projekt haben und einfach zwischen diesen wechseln.

Wenn ich bei einer Map im TreeView rechts klicke und dann Eigenschaften auswähle, funktioniert der Cancel Button nicht.

Das Hilfe Menü ist unfunktional.

Das Füll-Werkzeug funktioniert nicht.

Raster ein/ausschalten funktioniert nicht (muss erst minimieren, dann maximieren, also repainten)

Leider muss ich sagen: Die Software ist in dieser Form absolut unbrauchbar.

21.12.2008 - 15:29 Uhr

Muss sagen, das Ding funktioniert noch nicht.

Wenn ich mehrere Tiles auf einmal auswählen will, zieht er den Rahmen nicht korrekt (setzt viel zu weit oben an, das hat mit der Auswahl und der Cursorposition rein gar nichts am Hut).

Wenn ich neu starte, passiert überhaupt nichts, wenn ich den "Projekt Laden" Button drücke.

Ich kann die Passierbarkeit nur einmal setzen, danach lässt sie sich nicht mehr verändern.

Wenn ich "Testspiel starten" drücke, hängt sich das Spiel sofort auf (This game was compiled using the wrong version of the XNA Game Studio, ContentLoadException, pause_screen not found).

Auch wenn das UI schnieke aussieht, muss ich doch sagen: Absolut noch nicht veröffentlichungswürdig. Not yet an alpha.

21.12.2008 - 14:18 Uhr

Hallo!

Kann jemand von euch eine DVB-T Karte mit Antenne empfehlen?

Laut der Empfangsprognose hier genügt eine Zimmerantenne. Sollte man trotzdem auf Nummer sicher gehen und sich eine leistungsfähigere Antenne holen?

Wäre nett, wenn ihr eure Erfahrungen mit bestimmten Produkten hier mitteilt.

20.12.2008 - 15:34 Uhr

Kannst du mal ein Codebeispiel zeigen, wie man komplexe Objektgraphen (z.B. M:N Relation) holt, bearbeitet und abspeichert?

Hast du die Performance schonmal gemessen?

Ich persönlich empfinde es als ungewohnt, dass alle Klassennamen, Attribute etc. Deutsche Namen tragen. Ich denke, Englisch ist hier als Industriestandard vorzuziehen.

19.12.2008 - 17:01 Uhr

Würde mal sagen, du solltest in OnPaint abfragen ob das Device noch da ist.

if(Device == null) return;

Ausserdem räumst du ja nirgends sauber auf. Ziemlich sicher ist, dass irgendein EventHandler auf dem Close aufgerufen wird, der versucht auf etwas zuzugreifen, was schon weg ist.

19.12.2008 - 16:16 Uhr

Ja, das musst du dann noch machen.

Eigentlich ist es egal, ob du das Memory selber allozierst oder direkt ein float Array mit fixer Länge im Struct angibst. Wenn du irgendwo die Länge des float Arrays feststellen kannst, kannst du halt exakt soviel Speicher allozieren, wie du brauchst (Vorteil gegenüber einem fixen Array im Struct).

float[] x = new float[buffer];
Marshal.Copy(yourIntPtr, x, 0, buffer);

Alternativ halt:

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct tcMuxRead
{

    public ushort DasChan;
    public ushort DasGain;
    public ushort ExpChan;
    public ushort TCType;
    public ushort TempScale;
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.R4, SizeConst=BUFFERGRÖßE)]
    public float[] temp;
}
19.12.2008 - 15:57 Uhr

Ich nehme mal an, dass hier der Fehler auftritt:

returnValue = DRV_TCMuxRead(currentDriverHandle, ref dummyTCMuxRead);

Initialisier dein struct vorher:

Module.tcMuxRead dummyTCMuxRead = new Module.tcMuxRead();
dummyTCMuxRead.temp = Marshal.AllocHGlobal(BufferDerGroßGenugIst);
19.12.2008 - 15:39 Uhr

Zeig mal den ganzen Code. Vermutlich musst du für das Array vorher erstmal Speicher allozieren.

19.12.2008 - 15:28 Uhr

Hallo, Jaspar!

So müsste das aussehen:

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct tcMuxRead 
{
    
    public ushort DasChan;
    public ushort DasGain;
    public ushort ExpChan;
    public ushort TCType;
    public ushort TempScale;
    public IntPtr temp;
}

[DllImport("Adsapi32.dll")]
public extern static int DRV_TCMuxRead(int DriverHandle, ref tcMuxRead lpTCMuxRead);

Den IntPtr für die floats kannst du mit Marshal.Copy dann in ein float Array umwandeln.

HTH

19.12.2008 - 02:45 Uhr

Gib einfach die Mindestanforderungen vom .NET Framework an. Kunden sind das gewohnt g

18.12.2008 - 19:19 Uhr

Schaut euch doch einfach mal den DataFilter in Excel an. Der hat ein ziemlich schönes UI.

15.12.2008 - 21:51 Uhr

Was du brauchst id Linq2SQL oder das ADO.NET Entity Framework.

Tutorial:

http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx

Linq2SQL ist lightweight und recht einfach zu benutzen. Das Entity Framework ist etwas mächtiger. Performant ist beides nicht sonderlich.

14.12.2008 - 04:02 Uhr

lol, ob 2D oder 3D macht imho keinen großen Unterschied. Die Schwierigkeiten liegen ganz wo anders.

Kinders, ich sach euch:

DAS GEHEIMNIS SIND DIE SCHNITTSTELLEN!

14.12.2008 - 04:01 Uhr

Ihr Braucht Motivation

http://www.youtube.com/watch?v=KMU0tzLwhbE

STEVE BALLMER RULEZ!!!111oneeleven111!!!

13.12.2008 - 16:00 Uhr

SQLite sollte imt Unicode schon klarkommen. Benutzt du auch Version 3?

Wie holst du die Daten aus der DB? Welchen Provider benutzt du?

13.12.2008 - 12:09 Uhr

Schwer zu sagen, ob so etwas nochmal passiert. Ich habe einen Verdächtigen und würde ehrlich gesagt gerne dafür sorgen, dass er sich selber verrät.

Die Frage ist, wie man den, im Falle des Falles, am besten dazu bringt, von selbst ein Geständnis abzuliefern oder sich zu verraten.

13.12.2008 - 11:08 Uhr

Hallo Community!

Gestern Nacht hat jemand bei meinen Eltern mit einem Stein eine Scheibe an ihrem Auto eingeworfen. Die Garage stand immer offen, man geht ja nicht davon aus, dass so etwas passiert. Was uns stutzig macht: Das Auto wurde anscheinend gezielt rausgesucht, denn es war nicht unbedingt das nächstbeste Ziel, das sich so ein Vandale rausgesucht hätte.

Eigentlich haben wir keine Feinde, aber ich habe einen Verdächtigen. Nun frage ich mich, wie man so einen Täter am besten überführt. Irgendwie müsste ich da ne tricky Falle aufsetzen, damit er sich selbst entlarvt. Irgendwelche Ratschläge oder Tipps?

(p.s. Die Polizei kann man in solchen Fällen ja vergessen. Die nehmen das auf und damit hat es sich auch)

12.12.2008 - 17:30 Uhr

Naja, so mal ausm Kopf raus (auszugsweise):

<add key="ExcelSheet1HeadCol1" value="SomeHeader" />
<add key="ExcelSheet1HeadCol2" value="AnotherHeader" />

<!-- snip -->

<add key="ExcelSheet1HeadCol45" value="YetAnotherHeader" />

<add key="ExcelSheet1ColorCol1" value="45" />
<add key="ExcelSheet1ColorCol2" value="45" />

<!-- snip -->

<add key="ExcelSheet1DataTypeCol1" value="V200" /> <!-- V200 ist son Marke Eigenbau String typ - wird für die Formatierung benötigt -->
<add key="ExcelSheet1DataTypeCol2" value="N" />

<!-- snip -->

<add key="ExcelSheet1ForeignKey1" value="BLABLADONTKNOWSHIT" />

Ja, und davon halt 3000 Zeilen.

12.12.2008 - 17:25 Uhr

Du hast keine Ahnung, was für Perversionen man mit "XML" erstellen kann. Das Config File ist eine Mark-Up Vergewaltigung, die ihres gleichen sucht. Werds demnächst mal posten, hab z.Z. Urlaub. Dann weisst du, was ich meine.

12.12.2008 - 11:25 Uhr

Ich könnte einen ganzen Client hier posten....werde es aber nicht tun. Und ihr alle würdet beim Anblick des Codes sofort erblinden.

Ich nicht, ich bin stark. Ich hab eine rosarote Spezialbrille die mir durch den Tag hilft.

Ausschnitt:


public void ExportData1()
{
     object oExcelName;
     object oFileName;
     object[] oHeaders;
     object[] oDataTypes;
     object[] oAgg;
     object[] oData;
     object specColToReplace;

     oExcelName = "blablub";
     oFileName = "blabla";
     GetConfig(ref oHeaders, ref oDataTapyes, ref oAgg, ref specColToReplace);
     data = GetData(ref oHeaders, ref oDataTypes, reg oAgg, ref specColToReplace);
     ExcelSheet sh = new ExcelSheet(oHeaders, oDataTypes, oAgg, specColToReplace, data);
     ArrayList arlExcSheets = new ArrayList();
     arlExcSheets.Add(sh);
     Excel.Exp2ExcelMap(arlExcSheets, oFileName);
}

Kein Witz. Von dieser Sorte Methode gibt es ca 200 im ganzen Code. Und innerhalb der GetConfig Methoden etc. werden immer mehr Argumente angehäuft, die dann immer weiter per ref übergeben werden, immer tiefer in den CallStack hinein.

Try Catch Blöcke werden im Code so benutzt:


try
{
    //stuff
}
catch(Exception ex)
{
    throw ex;  //nichts weiter
}

Und den größten Horror, das "XML" Config File, hab ich euch noch erspart.

10.12.2008 - 19:05 Uhr

Da gibt es zig Möglichkeiten. Rich oder Fat Clients könnten die Berechnungen selbst durchführen, Thin Clients würden wohl eher die Arbeit der DB und den Zugriff selbiger oder einem Applikationsserver überlassen.

In einem heterogenen Umfeld setzt man wohl heutzutage auf Webanwendungen mit einem Browser als Rahmenapplikation oder Java, wenn man etwas mehr Ergonomie / Performance / Features im Client braucht. Wobei die eigentlichen Berechnungen hier wohl von den Servern getragen werden.

Die Frage ist, ob die Geschäftslogik mehr Richtung OLTP oder OLAP geht.

08.12.2008 - 17:45 Uhr

Abgesehen davon, dass der Weg mit dem versteckten Webbrowsercontrol einfach nur dreckig ist.

Hol dir einfach die Daten über einen WebRequest und setze die dann in ein HtmlDocument.

Edit: Darf doch nicht wahr sein, dass diese Klasse keinen öffentlichen Konstruktor hat. Da bleibt wohl wirklich keine andere Wahl als den Webbrowser zu nutzen.

08.12.2008 - 15:32 Uhr

Dir geht es wahrscheinlich darum, einen eigenen Event für dein Control zu erstellen:

http://www.devarticles.com/c/a/C-Sharp/Creating-Custom-Delegates-and-Events-in-C-sharp/

08.12.2008 - 15:30 Uhr

Ich würde es dem Programm, welches das Assembly nutzt überlassen, ob es in einem eigenen Thread laufen soll.

Dadurch gestattest du dem User mehr Kontrolle über den Ablauf. Allerdings könntest du ja beide Varianten anbieten, das wäre mit Sicherheit am komfortabelsten.

08.12.2008 - 15:20 Uhr

Allerdings geht es da noch um .NET 1.1.

Vielleicht hat sich da zwischenzeitlich etwas geändert. Und zudem sind die Implementierungen unbekannt.

08.12.2008 - 15:11 Uhr

http://www.cs.ru.nl/~marko/onderwijs/oss/RMI_and_Remoting.pdf

Da lag ich wohl falsch. Dieses Paper zeigt eindeutig, dass RMI wirklich in allen Belangen superior gegenüber .NET Remoting ist.

08.12.2008 - 14:52 Uhr

Theoretisch entschlackst du dadurch den Object Graph - also ja. Ob RMI sich so viel besser schlagen würde, wage ich zu bezweifeln. Der hatte da sicher kein vergleichbares Setup.

08.12.2008 - 14:41 Uhr

Das muss ja dann schon ein kleiner ObjectGraph serialisiert werden.

9 000 Objekte * 10 Properties und zusätzlich der Object Graph. Da wirkt die benötigte Zeit auf mich noch kurz.

MediaList ist so wie es da steht unnötiger Overhead. Glaube kaum, dass du diese Menge in einem anderen Format (z.B. XML) schneller übertagen könntest.

Wenn wir nur mal davon ausgehen, dass jedes Property 20 Bytes an Daten enthält, dann sind das ca. 1,7 MB. Dafür ist das ganze ja noch schnell.

08.12.2008 - 14:02 Uhr

Von der Channelseite gesehen passt eigentlich alles. Zeig mal, was für Objekte du da überträgst. Und vor allem: Wie viele sind es?

Zeig mal den Code. Ich vermute, du rufst da einfach in irgendeiner Schleife x mal eine Methode auf.

08.12.2008 - 13:43 Uhr

Benutzt du rohe Übertragung per TCP Channel mit einem BinaryFormatter?

08.12.2008 - 13:10 Uhr

HttpWebRequest
GetResponse()

Nein, du brauchst keinen versteckten Browser.

08.12.2008 - 12:43 Uhr

Das habe ich so nicht gemeint und Leider habe ich im Moment auch keine Muße, mal ein Beispiel zu stricken. Vielleicht heute Abend.

08.12.2008 - 11:02 Uhr

Von hetzner hört man durchweg nur Positives!

08.12.2008 - 10:50 Uhr

Nur die Kenner können mit 10 Fingern bis 255 zählen !!

Und nur die wahren Kenner können mit 10 Fingern bis 1023 zählen !!

SCNR 😁

07.12.2008 - 23:23 Uhr

Du, nimm du mal NHibernate. Das Java Vorbild ist quasi Industriestandard. Und versuch auch dein DB Schema selber zu designen. Du wirst viel lernen.

Mein Gott, ich bin hacke. Aber das Ballroomquiz war cool.

07.12.2008 - 19:21 Uhr

Die vertikale Schicht ist dann meine List <T>? Bzw. was sind genau Business Objekte, hab das jetzt nicht ganz genau verstanden 😉. Und in wie fern muss diese allen anderen Schichten bekannt sein, ich meine wenn die Businessobjekte meine Objekte sind, mit denen ich arbeite, dann versteh ich es. Denn die Datenzugriffsschicht braucht die Objekte ja um sie zu speichern, und die Präsentationsschicht muss sie kennen, da sie die Objekte ja anzeigt.

Im großen und Ganzen richtig, aber komm von dieser Ausdrucksweise von List<T> weg. Schließlich geht es hier nicht um konkret im Speicher vorhandene Objekte und auch nicht um Listen, sondern um die Kenntniss der Typen der Business Objekte in den anderen Schichten.

Du wirst aber zweifelsohne in der Logikschicht oder der Präsentationsschicht mal Listen von Business Objekten haben.

Da fällt mir ja ein Stein vom Herzen 😉. Es ist also wirklich so einfach, dass ich meine Objekte nur übergeben muss, der O/R Mapper ALLES alleine macht und ich die fertigen Objekte wieder bekomme? SQLite scheint recht gut für mein Programm zu sein, sollte auf jeden Fall Embedded sein, bzw. es muss kein Server im Hintergrund laufen.

Der Teufel steckt immer im Detail und ob es dann alles so einfach ist, wage ich zu bezweifeln. Ich persönlich würde lieber die Objekte aus einem Schema erzeugen, weil dadurch gewährleistet ist, dass die Daten auch so abgespeichert sind wie ich mir das vorstelle und unter Umständen andere Applikationen besser mit der selben DB arbeiten könnten (die unter Umständen keinen oder einen anderen O/R Mapper einsetzen).

Habe schon von einigen O/R Mappern gehört NHibernate, SubSonic.... Aber die klingen alle relativ "Mächtig" und vielleicht etwas überdimensioniert für mein "kleines" Programm. Hättest du da eine Empfehlung für mich, die auch das Datenbankschema und so für mich erstellt?

Ich habe nur mal mit Hibernate unter Java rumgespielt, noch nie einen O/R Mapper in einem richtigen Projekt eingesetzt. Ich hab immer auf typisierte DataSets und ADO.NET gesetzt, wenn ich einen kleinen OLTP Client gebraucht hab. Deswegen frägst du an dieser Stelle besser jemand Anderen 😃

07.12.2008 - 18:40 Uhr

Halo JuyJuka,

ja, ich gehe davon aus, dass ich mit Objekten arbeiten werden (wie du anmerkst macht es ja auch Sinn, eine Bewerbung kann ein schönes Objekt sein mit seinen Properties (Termine, etc).

Es könnte auch easy peasy in einem typisierten DataTable drin stehen.

Ich kann also eine List<T> (also typsicher, stimmts?) mit den Objekten füllen und diese dann mittels BindingSource Objekten an meine Darstellungsschicht (sprich meine Controls) binden.

Ja, das könntest du tun. Typsicherheit ist deswegen gut, weil du type-mismatches zur Compiletime feststellen kannst, sprich, ein Fehler der zur Kompilierungszeit gefunden wird, hat keine Chance drin zu bleiben und schafft es nicht bis zum Kunden.

Wie heißt diese Schicht dann eigentlich? Ich mein meine Controls sind ja quasi die Darstellunsschicht / Präsentationsschicht?

Das ist eine vertikale Schicht und die nennt sich Business Objekte. Diese vertikale Schicht sollte allen anderen Ebenen bekannt sein. Die Schicht, die sich um die Persistierung selbiger kümmert, nennt sich Datenzugriffsschicht.

Naja egal, speichern würde ich das ganze dann mit einem O/R Mapper. Wenn ich das richtig verstanden habe (Versuche grad "Grundsatz"Literatur zum Thema O/R Mapper zu finden), kann ich dem O/R Mapper meine Objekte einzeln übergeben (oder vielleicht auch direkt die List<T>?). Dieser speichert die dann in einer Datenbank (muss ich die Tabellen dafür selber anlegen, oder übernimmt das alles der O/R Mapper? Besondern im Gesichtspunkt der Normalisierung). Wenn ich die Daten lade, bekomme ich vom Mapper meine fertigen Objekte wieder / meine List wieder, mit der ich wieder arbeite.

Bin ich da auf dem richtigen Weg?

Objekte können sich z.B. mittels einer Save() Methode z.B. selbst wieder persistieren, man muss nichts weiter übergeben, das hängt aber auch vom eingesetzten Framework ab. In den meisten Fällen läuft es wohl so, wie du dir das vorstellst. Wenn du die Daten lädst, bekommst du von der Schnittstelle selbstverständlich deine fertigen, typisierten Business Objekte zurück.

Du kannst mit einigen O/R Mappern übrigens auch das komplette Datenbankschema aus deinen Business Objekten erzeugen lassen.

07.12.2008 - 13:17 Uhr

Siehe auch: http://www.onlamp.com/pub/a/onlamp/2006/04/20/advanced-mysql-replication.html

Sektion: Circular replication with two nodes

07.12.2008 - 13:09 Uhr

Also ich würde mir halt einfach einen Root-Server mieten bei dem du selbst die DB konfigurieren darfst. Das kostet doch auch nicht wesentlich mehr.

Dann ganz normale Replikationstechniken anwenden:

http://www.howtoforge.com/mysql_database_replication

Ist doch einfach.

07.12.2008 - 10:09 Uhr

Kann ich auch bestätigen.

07.12.2008 - 10:07 Uhr

Hallo, ProGamer!

Ich bestätige hiermit deinen Fund. Die Signatur scheint immer noch drin zu sein, ein 1x1 Pixel großes Bild names lolv.bmp. Sieht im Hexeditor sehr verdächtig aus.

Ich finde, flotse sollte sich dafür rechtfertigen müssen, schließlich glaube ich nicht, dass dieses Bild zufällig auf seinen Webspace und in seine Signatur kommt.

06.12.2008 - 17:58 Uhr

(Sorry, ich kann eigentlich nur konkret denken.)
Du meinst also, wenn er eine Fahrzeugverwaltung schreibt, dann hätte eine Metadatenbank den Vorzug, wenn nun noch die Fahrad-Verwaltung nachträglich mit hineinzunehmen wäre, bräucht an einer Metadatenbank nichts geändert zu werden.

Quasi. Man müsste eigentlich nur den Client anpassen. Die Änderungen an der DB wären minimal.

Wie realistisch ist dieses Szenario?

Was, wenn die Abläufe der FahradVerwaltung anders strukturiert sind?

Es geht hier doch nicht um Abläufe sondern um blanke Datenhaltung.

Und nun die Kosten einer MetaDB: Keine sprechende Benamung, Abfragen müssen zusätzlich die Attribute spezifizieren.
Typisierung?

Zur not Views bauen die Pivotieren und casten. Dann hat man genau was man will, aber wesentlich weniger DB Objekte zu warten. Das man dies durchführen müsste, ist natürlich ein Nachteil, aber es ist vom Aufwand immer noch geringer als lauter unnötige Tabellen zu erstellen.

Was, wenn die Mitarbeiter von den Autos Bildchen sehen wollen, und von den Fahrrädern nicht?

In die Attribut-Tabelle könnte natürlich ein Blobfeld für Binärdaten sein.

Die Kosten einer MetaDB sind kontinuirlich über den gesamten Entwicklungszeitraum (und Support).
Neuschreiben nach Maß hat eigentlich nur (evtl!!) während der Datenmodellierungs-Phase höhere Kosten.
evtl!!, weil selbst in der Modellierungs-Phase vermutlich die komplexere Struktur einen höheren Aufwand verursacht.

Denke ich ehrlich gesagt nicht. Und selbst wenn, dann rechnet sich das für manche Szenarios. Man bleibt einfach leichter erweiterbar und muss für viele Fälle nur simple Anpassungen am Client vornehmen. Wenn man von der Pivotierung absehen kann, weil man sie nicht braucht, braucht man überhaupt keine Anpassungen an der DB vornehmen!

Nach der ModellierPhase muß alles weitere eh neu geschrieben werden, man kann ja nicht die Fahrzeug-Steuereelemente für die Fahrräder verwenden.

Das Schema lässt dies zu, wenn der Client es so möchte. Oder man baut Check-Constraints ein. Es ist einfach simpel und wenn der Client keinen Fehler beim Einfügen macht, was sowieso nicht vorkommen sollte, gibt es hier auch keine Probleme.

Ich schätze das Verhältnis ModellierPhase/Implementierung auf sagenwa 1:200, und wenn die Implementierung sich dann ständig mit unlesbaren Namen herumschlagen muß, und jede Abfrage ein Stück komplexer ist - also iwi habich noch nix verstanden, von den vorteilen einer MetaDB.

Das ist sehr großzügig geschätzt. Wenn man ein Programm richtig plant, schätze ich dass es insgesamt fast auf 1:1 hinausläuft. Ich verrechne hier aber Modellierung allgemein, nicht nur auf die DB bezogen.

Es ist schon klar, dass so eine "MetaDB" gravierende Nachteile hat:

* Typsicherheit
* Muss-Spalten
* Evtl. komplexe Datenzugriffslogik (abhängig vom Szenario)

Aber es gibt auch Vorteile:

* Flexibilität / Erweiterbarkeit
* Simplizität

Für einen Objektkatalog bei dem von Vornherein noch nicht ganz klar ist, welche Objekte und vor allem welche Informationen zu diesen abgespeichert werden sollen, ist so ein Ansatz doch ideal.