Laden...
Avatar #avatar-3273.gif
Mr. Bart Simpson myCSharp.de - Member
Anwendungsentwickler Mittelfranken Dabei seit 13.03.2004 502 Beiträge
Benutzerbeschreibung

Forenbeiträge von Mr. Bart Simpson Ingesamt 502 Beiträge

15.04.2008 - 22:20 Uhr

Wenn die Werte, nach denen Du "sortierst" (Spalte 6) eindeutig sind, geht das sehr einfach mit einem Group By innerhalb einer "dazugejointen" Subquery, wobei der gesuchte Wert (das Maximum) das Join-Kriterium wird.
Bei nicht-eindeutigen Werten gilt das gleiche Grundprinzip, aber es müssen alle zur Selektion des richtigen Datensatzes nötigen Werte (z.B. Das Maximum einer anderen Spalte) ebenfalls ins Join Kriterium aufgenommen werden.

Bart Simpson

27.01.2008 - 13:15 Uhr

Bart Simpson liegt deshalb falsch, weil das die Anzahl der betroffenen Zeilen liefert. Jürgen

Du hast natürlich recht... Hab wohl einfach die falsche Methode erwischt - ExecuteScalar wär's gewesen 😉

Bart Simpson

26.01.2008 - 17:32 Uhr

Ungefähr so?

cmd.Connection = con;
cmd.CommandText = "SELECT Kostenstelle_ID from Kostenstelle" +
                                "WHERE (Kostenstelle = [selectedKostenstelle] )";
con.open();
int id = (int) cmd.ExecuteNonQuery();

Bart Simpson

21.11.2007 - 18:01 Uhr

Original von CrazyPlaya
Was ist wenn ich CAST praktisch standardmäßig verwende? Geht das stark auf die Performance?

Bin ich mir nicht sicher. Normalerweise würde ich sagen, dass der SQL Server so clever ist und ein CAST auf den selben Datentyp gar nicht erst ausführt. Der Ausführungsplan auf einem SQL Server 2000 sagt mir aber was anderes... Solltest Du einfach mal "ausmessen".

Original von CrazyPlaya
Die ganze Sache soll ja ebenso gut mit dem SQL Server 2000 funktionieren.
Und da gibt es nvarchar(max) meines Wissens nach ja nicht.

Korrekt - das gibt's erst seit SQL Server 2005.

Bart Simpson

21.11.2007 - 17:32 Uhr

Wäre dann nicht die ADO.net Variante genau das Richtige? Damit kannst Du doch Clientseitig genau die Datentypen abfragen und dann Deine Query entsprechend aufbauen...

CAST kannst Du theoretisch immer verwenden, denn ein CAST von nvarchar auf nvarchar macht nichts...

Aber mal nebenbei: SQL Server 2005 bietet eine sehr schöne Lösung für Dein Problem - nämlich nicht mehr ntext zu verwenden, sondern nvarchar(max) - damit funktioniert alles was mit nvarchar(200) auch geht...

Bart Simpson

20.11.2007 - 17:54 Uhr

Schau Dir doch mal die Doku zu folgenden Systemtabellen (bzw. Kombatibilitätsschichten im SQL 2005) an:

SELECT * FROM syscolumns
SELECT * FROM systypes

[Edit]: Oder die ADO.net Alternative SqlConnection.GetSchema

Bart Simpson

17.11.2007 - 17:33 Uhr

Versteh ich das richtig? Wenn eine Tabelle keine Datensätze enthält, dann kriegst Du kein (auch kein leeres) Result-Set, sondern es wird ein Fehler geworfen? Kann ich mir irgendwie nicht vorstellen... Ich behaupte mal frech, da muss ein Problem in Deiner Abfrage sein 😉

Poste doch mal die Grundstruktur Deiner Abfrage - evtl. kann Dir dann geholfen werden.

Bart Simpson

17.11.2007 - 17:26 Uhr

Versuchst Du auf ein gemapptes Netzlaufwerk zuzugreifen? Das wird nicht (so einfach) klappen. Der Dienst läuft (auch wenn er in Deinem Benutzerkontext läuft) nicht in der selben Anmeldung wie Du, wenn Du Dich selbst anmeldest - es werden keine Netzlaufwerke gemappt. Verwende stattdessen UNC Pfade - dann klappt's auch mit dem Nachbarn 😉

Bart Simpson

07.11.2007 - 22:02 Uhr

Es gibt auch ein vordefiniertes Symbol dafür:


#if DEBUG
  //Debugcode
#endif

Allerdings bezieht sich das (afaik) nicht darauf, ob wirklich ein Debugger "dran hängt", sondern nur, ob der Compiler auf Debug stand, als die Assembly erzeugt wurde.

Bart Simpson

07.11.2007 - 21:53 Uhr

Nur so am Rande: Windows Authentifizierung geht sehr wohl auch, wenn man nicht beide Rechner in einer Domäne hat - man muss nur wissen wie und welche Konsequenzen das hat.
Möglich ist es, wenn man zuerst mal vom Client zum Server eine Verbindung via Filesystem (aka Explorer) aufbaut. Dann fragt Windows typischerweise nach Benutzernamen und Passwort. Wenn das Passwort dann noch gespeichert wird, klappt die Windows Anmeldung auch für den SQL Server (zumindest, wenn Du den SQL Server erst danach versuchst - ansonsten ist ein Neuanmelden nötig).

Alternativ kannst Du auch (bei Win XP Pro, bei Home bin ich nicht sicher) via Systemsteuerung->Benutzerkonten-> Erweitert (u.U. muss erst von der "grafische Anmeldung in den "normalen" AnmeldeModus gewechselt werden). Dann gibt's auf den Reiter "Erweitert" die Netzwerkkennwörter (Achtung, das geht afaik nur so, nicht via MMC Snap-In).
Beim Win2K3Server gibts für die Netzwerk-Kenwörter einen extra Systemsteuerungspunkt.

Jdenfalls muss der Benutzername und das Passwort für den Zielserver (auf die eine oder andere Weise) am Client hinterlegt worden sein (mit all den "Nebenwirkungen, die gespeicherte Passwörter eben haben), wenn man nicht in der selben Domäne (oder nur einer Arbeitsgruppe) ist - Dann klappt's auch mit dem Nachbarn 😉

Bart Simpson

[Edit]: Wenn der Benutzername nicht hinterlegt wurde, "weiss" Windows eben nicht, womit es sich den authentifizieren soll, was genau in Deiner beschriebenen Fehlermeldung ("Keine vertraute Verbindung... Benutzer (null)..." resultiert

07.11.2007 - 13:42 Uhr

Spontan fallen mir da zwei Mögliche Ursachen ein:

  1. Die Windows Firewall (oder etwas in der Art)
  2. Wurde der SQL Server Dienst nach dem Erlauben der Remoteverbindungen neu gestartet?

Bart Simpson

P.S. Remote-Verbindungen sind beim SQLExpress prinzipiell schon möglich.

05.11.2007 - 09:31 Uhr

Also ich würde mal genau auf das tippen, was auch die Fehlermeldung sagt: Wahrscheinlich sind keine Remoteverbindungen erlaubt (Das ist standartmässig so bei SQL Server 2005).

Und ich denke mal deine VM hat eine andere IP als dein Rechner eigentlich hat (was aber egal sein dürfte, da eben standartmässig nur vom Loopback (127.0.0.1) Anfragen angenommen werden.

Kuck mal im Startmenü nach "SQL Server-Oberflächenkonfiguration" (ich hoff das heisst in der Express-Edition genau so), da kannst Du die Verbindungen konfigurieren und die Remote-Verbindungen (wohl am besten für TCP/IP) erlauben.

Bart Simpson

02.11.2007 - 12:38 Uhr

Also ohne das jetzt geprüft zu haben, aber ich würde drauf wetten, dass das Verwenden von Parametern in Verbindung mit IN so nicht funktioniert. SQL kennt keine Arrays (was Du hier im Prinzip versuchst nachzubauen).

Da Du Dein SQL sowieso schon dynamisch in C# zusammenbaust (worüber man sich allein schon trefflich streiten könnte, aber das ist ein anderes Thema), kannst Du doch (zumindest für den IN-Teil) das Kommando direkt (also ohne Parameter) zusammenbauen...

Bart Simpson

25.09.2007 - 20:48 Uhr

Sehr nett und noch günstiger ist auch der IO Warrior von Code Mercenaries.
Der ist zwar eingentlich für Joysticks gedacht, lässt sich aber (wie die c'T auch mal gezeigt hat) sehr schön "missbrauchen", und die C-API lässt sich sehr leicht in C# kapseln.

Bart Simpson

18.09.2007 - 21:05 Uhr

Original von BerndFfm
Bei deinem Pseudocode werden ja nur einzelne Tabellenzeilen kurz gesperrt und geändert. So kann kein Deadlock entstehen. Ein Deadlock kommt vor wenn sich verschiedene Sperren gegenseitig sperren, weil sie auf jeweils mehrere Tabellen zugreifen.

Ebensowenig kann es passieren mehrere Clients die gleichen Datensätze bekommen.

Wenn das in der Praxis der Fall sein sollte, dann verstehe ich nicht mehr was eine Transaktion ist.

Der Meinung war ich eigentlich auch... Aber ich bin zumindest Teilweise eines besseren belehrt worden. Den Punkt dass mehrere Clients den gleichen Datensatz bekommen, kann ich aber getrost ausschließen - das war wohl ein Problem in einer anderen Routine, was nur so aussah, als hinge es an meiner Methodik...

Die Deadlocks hingegen hatte ich dennoch weiterhin. Mittlerweile hab ich aber auch das in den Griff bekommen (zumindest schaff ich es nun nicht mehr, wenn ich >500 Threads nahezu zeitgleich drauf los lasse, einen Deadlock zu bekommen).

Den Durchbruch für mein Problem brachte der Deadlock-Graph des SQL Profilers (wobei ich mangels guter Lektüre zu dem Thema und in dieser fachlichen Tiefe nur hoffen kann, dass ich das richtig interpretiere....) 🤔

Das UPDATE Statement am Anfang hat ein Sub-SELECT um die Daten auszuwählen. Wenn nun Thread #1 prinzipbedingt erstmal einen Shared-Lock (zum Lesen) auf den betroffenen Datensatz (bzw. Tablerow und/oder -page) setzt, dann kann dies auch "zeitgleich" Thread #2 tun. Folgt nun bei einem der beiden Threads das Update, so "beantragt" der die Erhöhung des Lock-Levels für sich. Und schon haben wir den Deadlock, da entweder ein sog. Lost-Update oder aber ein Non-Repeatable-Read auftreten würde. Das erkennt der SQL Server und schmeisst einen der Threads via Deadlock raus.

Die Lösung ist ein Tablehint beim Sub-SELECT, um gleich ein Update-Lock zu beantragen, damit der zweite Thread gar nicht erst zum Zuge kommt, sondern schlicht warten muss, bis der erste fertig ist.

Bart Simpson

18.09.2007 - 13:12 Uhr

Deadlocks sind doch immer mal wieder ein Spass :evil:

Für den Anfang findest Du ein paar Grundregeln hier oder hier (beides in English, den MSDN Link gibt's aber auch in Deutsch - allerdings in einer "hässlichen" maschinellen Übersetzung).

Im SQL Server 2005 kann der Profiler recht nützlich sein, wenn Du den Deadlock - Graphen aktivierst. Da kann man recht gut die verschiedenen Lock-Levels sehen.

Bart Simpson

18.09.2007 - 13:03 Uhr

Kleine Anmerkung zum Konzept "Backup und Restore": Das ist aber nur dann empfehlenswert, wenn man im Prinzip zwei identische SQL Server hat. Für den Fall, z.B. von einer Developer Instanz in ein Life-System zu "kopieren", kann das zu übelsten Problemen führen, da im DB-Backup nicht nur die das drin ist was man meinen könnte, sondern auch "Struktur-Informationen" des SQL Servers.

Bart Simpson

14.09.2007 - 20:01 Uhr

Original von FZelle
Meist ist, wenn so ein Problem auftaucht, schon der Ansatz suboptimal.
Muss das so sein? Darüber hab ich auch schon nachgedacht. Das Ganze System (es besteht bei weitem nicht nur aus meinem "Problem-Teil") ist allerdings ansonsten trotz immenser Datenmengen mit dem SQL Server recht gut zu handhaben und auch performant.

Original von FZelle
Die MSMQ ist solange vorhanden, wie der Rechner der die hostet nicht gekillt wird. Was heisst "gekillt"? Bist der Rechner ausgeschaltet / neu gestartet wird? Oder überlebt die Queue auch einen Neustart?

Original von FZelle
Und wenn Du 10 Millionen Datensätze in ein paar Tagen verarbeiten willst, solltest
Du viel mehr zeit mit anderen Technologien und Architekturen verbringen. Naja, darüber kann man nun streiten... Ich halte den SQL Server grundsätzlich für recht gut geeignet als "Backend". Aber klar - es gibt immer Technologien, die unter gewissen Umständen erst richtig interessant werden.

Bart Simpson

14.09.2007 - 11:37 Uhr

Mal sehen ob ich den Ansatz richtig versteh:

Via SqlDependency kriegt meine Business-Logik mit, wenn sich was passendes in der DB ändert und ballert dann den/die entsprechenden Einträge in die MSMQ (Was die konkurierenden Zugriffe minimieren soll, da das bei "jeder" Änderung (also nahezu pro zur Verfügung stehenden Datensatz) passiert).
Aus der MSMQ bedient sich dann die Menge der Clients und arbeitet sie somit ab.

Soweit richtig? Wenn ja, dann hab ich aber immer noch ein paar Probleme:

  • Es gibt "Batch-Updates". Will heissen: Die Statusänderung eines Datensatzes kann Einfluss haben auf die "Abarbeitbarkeit" von X anderen Datensätzen.
  • Wie persistent sind denn Einträge in der MSMQ? Es kann (durch versch. Prios und "Arbeitsauslastung") u.U. sehr lange (>1 Woche) dauern bis ein Eintrag abgearbeitet wird - aber es darf nichts verloren gehen!
  • Beherscht die MSMQ überhapt eine Priorisierung? Falls das nicht klar rüberkam: Was ich will ist ein Verhalten á la: "Wenn ein Eintrag mit Prio 1 JETZT reinkommt und ein Client nach Arbeit fragt, dann kriegt er den - egal ob 10 Mio Datensätze mit Prio 2 schon seit Tagen warten."

Bart Simpson

P.S. Ich muss zugeben, langsam wurmt's mich und ich denk mir "Das muss doch sauber und perfomant in SQL gehen - aber wie zur Hölle mach ich das?"
Deswegen hab ich evtl. ein wenig "Scheuklappen" in Bezug auf den MSMQ-Ansatz... Klingt aber trotzdem interessant 👍

13.09.2007 - 18:45 Uhr

Original von FZelle
Wenn alles in der DB Abläuft, läuft aber ziemlich vieles schief.

Ok - die Formulierung war vielleicht etwas überspitzt, aber im Prinzip macht die Datenhaltung (sprich: Status- und Inhaltswerte) eben aus, was, wann, in welcher Reihenfolge abgearbeitet wird. Und das finde ich nun nicht grade verwerflich...

SqlDependency kenn ich (noch) nicht - seh ich mir aber gleich mal an...
Trotzdem, das Grundproblem bleibt bestehen, ich muss (wie auch immer) die Daten aus der DB holen - und da knallts eben.

Bart Simpson

13.09.2007 - 14:04 Uhr

Original von FZelle
Aber wenn dein JobSheduler die Aufgaben in diese Queue hineinschreibt,
kann jeder beliebige Client diese der reihe nach herauslesen.

Klingt ja an sich nicht schlecht... Aber meine "Aufgaben" ergeben sich aus Daten bzw. Datenänderungen innerhalb der DB - sprich: es läuft erst mal alles (wesentliche) in der DB ab. Von daher wäre das ja keine wirkliche Lösung, denn ich müsste die Daten auch erstmal aus der DB holen und in die MSMQ eintragen.

Das Problem ist ja auch nicht die prinzipielle Logik, die dahinter steckt, sondern vielmehr die Probleme die sich durch konkurierende Zugriffe von vielen Clients ergeben.

Bart Simpson

13.09.2007 - 09:50 Uhr

Original von FZelle
Warum SqlServer?

...weil alle relevanten Daten numal schon im SQL Server liegen?!

Original von FZelle
Für soetwas ist doch explizit die MessageQueue (MSMQ) gedacht.

Ach ja? Also ich hab zugegebenermaßen noch nicht wirklich mit MSMQ gearbeitet - aber ist das nicht eher dafür gedacht, Nachrichten zwischen Enpunkten zu transportieren?
Falls ich mich da irre - wie macht man den sowas bitte mit MSMQ?

Bart Simpson

13.09.2007 - 09:09 Uhr

Na, das ging aber schnell 8)

Leider helfen mir Eure Antworten nicht wirklich weiter.... Aber meine leicht ansteigende "Frustrationskurve" hat mich wohl dazu gebracht, nicht allzuviel in den eigentlichen Post reinzuschreiben - von daher: Mea Culpa 😉

Das hab ich jetzt mal nachgeholt in Form von ein wenig Pseudo-Code. (-> siehe OP)
Und weil ich schon dabei war, hab ich auch mal das Thema geändert... Vielleicht fühlt sich dann der ein oder andere zusätzlich angesprochen :evil:

Zum eigentlichen Thema: Eure Vorschläge (Transaktionen, Datensätze blocken, Zeitstempel, etc.) hab ich (IMHO) allesamt schon drin bzw. mal ausprobiert... Resultat waren eben immer genau die angesprochenen "Seiteneffekte" (@ikaros: Nein, ich meinte nicht die von Dir angesprochenen - aber dafür musst ich mich erstmal kugeln vor lachen... Von daher: You made my day!)

Um das Ganze mal genauer ausprobieren zu können hab ich mir sogar schon eine "Stress-Test"-Applikation geschrieben: Ich erzeuge dabei mal eben 50-100 Threads, von denen jeder eine Connection aufbaut und Die Stored Procedure aufruft - und das Ganze mit einen nahezu Worst-Case Szenario, nämlich innerhalb von ca. 50 ms (zumindest zum "auslösen" der SP).

@0815Coder: Suche? Meinst Du hier im Board oder googlen? Beides bringt mich nicht wirklich weiter... und wenn ich das Thema an sich richtig verstehe, dann hilft es auch bei meinem Problem nicht, da ich eher die pessimistische Variante bräuchte um die Datensätze nicht mehrfach zu verteilen...

Bart Simpson

12.09.2007 - 20:32 Uhr

verwendetes Datenbanksystem: MS-SQL ab 2000

Ich arbeite gerade an der Implementierung eines Business-Layers, dass im Prinzip wie folgt arbeiten soll:
In einer Tabelle sind Daten abgelegt, die nach einer gewissen Logik sortiert (->Priorität) abgearbeitet werden müssen.
Dafür verbindet sich mein Client mit der DB, holt sich den nächsten Datensatz, arbeitet ihn ab und schreibt die Ergebnisse wieder zurück.
Im wesentlichen also genau das was hinter einer Queue steckt.

Nun aber zum Problem: Es gibt eine größere (>50) Zahl an Clients, die gleichzeitig daran arbeiten sollen...

Je nach Implementierung komme ich nun aber zu gewissen Seiteneffekten: 🤔
Entweder es treten Deadlocks auf, wenn sich mehrere Clients gleichzeitig den nächsten Datensatz holen möchten.
Oder es treten Timeouts auf, wenn ein Client warten muss, bis der "vorherige" Client fertig ist mit dem Abholen.
Oder es werden die gleichen Datensätze an mehrere Clients gleichzeitig ausgegeben.

Allesamt sehr unschöne Seiteneffekte X(

Wie würdet Ihr sowas implementieren? Irgendwelche Vorschläge?

Sehr interessant wäre auch etwas "tiefgründigere" Info zum Thema, wie man Deadlocks am besten vermeidet.

EDIT: Damit meine bisherige Vorgehensweise besser verständlich wird, hier mal ein wenig "Pseudo-Code" aus meiner Stored Procedure, die den nächsten Datensatz zur Bearbeitung liefern soll:

DECLARE @SessionID uniqueidentifier
SELECT @SessionID = NEWID() -- Eindeutige Kennung für die aktuelle Session/Clientverbindung


BEGIN TRANSACTION

UPDATE Queue
  SET SessionID = @SessionID, ProcessingTimeStamp = GETDATE()
  FROM Queue 
  INNER JOIN 
  (  -- Sub-Select zum finden des nächsten zu bearbeitenten Eintrags
	SELECT TOP 1 ID FROM QUEUE
	WHERE SessionID IS NULL -- Bereits vergebene werden nicht mehr bearbeitet
	AND ... --- Eigentliche Filterkriterien für die Bearbeitung der Queue
    ORDER BY ... -- Prio-Sortierung
  ) AS FilteredQueue
  ON Queue.ID = FilteredQueue.ID
  WHERE SessionID IS NULL -- Bereits vergebene werden nicht mehr bearbeitet
  
COMMIT TRANSACTION -- Transkation so kurz wie irgend möglich, damit die Sperren so kurz wie möglich gehalten werden


-- Hier erfolgt die eigentliche Datenrückgabe an den Client
SELECT * FROM Queue WHERE SessionID = SessionID

Bart Simpson

10.09.2007 - 21:01 Uhr

Also ich würde eher zu DATEADD raten - das ist genau das was Du suchst...

Update Auftrag set Datum = DATEADD(year, -100, Datum) 

Bart Simpson

31.08.2007 - 13:38 Uhr

Original von D.Follmann
Was meinst du damit genau?!?

"property" ist ein sehr schlechter Name für ein struct, da das ein Schlüsselwort ist...

Zum Thema: Kann ich mal die Originaldefiniton für das Struct (und am besten auch den Funktionsaufruf) sehen (ich nehm mal an das ist 'ne C++ Dll), nicht nur das VB-Interface?

Warum er den StringBuilder hier nicht marshallen kann, versteh jetzt auch grad net... hast Du da mal ein paar "Codefragmente"? - Dann kann ich evtl. was sagen.

Die Idee mit dem Byte-Array müsste allerdings auch funktionieren... Kann aber sein, dass die DLL hier fiese Sachen treibt und Du dann erst mal ein GlobalLock aufrufen musst, bevor Du die Daten holst.

Bart Simpson

31.08.2007 - 10:26 Uhr

Zu allererst mal: Es ist keine gute Idee, einen Typen wie ein Schlüsselwort zu verwenden...

Zum Thema: Wenn ich Dich richtig verstehe, dann versuchst Du irgendeine native DLL aufzurufen, die Dein struct (und insbesondere den String) <<füllt>> ?
Dann brauchst Du aller Wahrscheinlichkeit nach einen StringBuilder, der vorher instantiiert und auf die richtige Größe gebracht wird.
Hier mal (ungetester) Demo-Code:


public struct data
    {
        public int a;      
        public int b;      
        public int c;      
        public int d;      
        public int e;          
        public int f;        
        public byte txtLen;      
        public Stringbuilder txt;        
    }

public data d;
d.txt = new Stringbuilder();
d.Capacity = 150; // besser zu viel als zu wenig reservieren - Muss Du aber ausprobieren...

...
 <<Aufruf der DLL hier>>

Bart Simpson

29.08.2007 - 08:52 Uhr

Original von d.gierse
@Bart: hast du was raus gefunden ?

Ja, aber wird dir nicht gefallen... scheint als ist das ein "normales" OCX, das immer registriert sein will. (Ich hatte allerdings nicht die Zeit, da größer was zu testen!)
Du kannst aber sehr leicht selbst damit experimentieren: Einfach die Demo-Version Downloaden und einbinden - die ist identisch mit der "Kauf-Version" - es wird nur keine Seriennummer beim instatiieren angegeben.

@CB.NET: Kennst Du Details zu dem Webservice? Ist der kostenpflichtig, stabil, zuverlässig... ? Auf der Seite selbst ist leider nicht wirklich was darüber zu lesen.

Bart Simpson

26.08.2007 - 13:16 Uhr

Das gibt's aber auch als API Call: NetUseAdd aus NetApi32.dll. Details dazu findest Du in der MSDN.

Bart Simpson

25.08.2007 - 12:53 Uhr

Bin mir jetzt nicht 100%ig sicher, aber wenn ich mich recht entsinne, ist es nicht zwingend nötig gewesen, das OCX zu registrieren. Ich kann das aber, wenn Du möchtest, nächste Woche (wenn ich wieder in der Firma bin..) mal ausprobieren.

Bart Simpson

23.08.2007 - 19:03 Uhr

Also ich benutze dazu das OCX von sev

Ist nicht das tollste - aber es tut seinen Dienst.

@robbyrc: Im Prinzip richtig - aber wenn es um die Prüfung der Kontonummer geht, dann wird das kein Spass, denn es gibt mehr als 100 verschiedene Prüfverfahren...

Bart Simpson

23.08.2007 - 16:54 Uhr
DBCC CHECKIDENT (Tablename, RESEED)

Bart Simpson

02.08.2007 - 00:06 Uhr

Kleine Anmerkung am Rande: Ich würde Dir die DATEADD Funktion empfehlen - damit bist Du wesentlich flexibler als mit Deiner Lösung (die natürlich auch geht...)

Bart Simpson

01.08.2007 - 23:38 Uhr

Ich hab mal in meinem alten Sourcecode von damals gewühlt und dabei folgendes gefunden - wenn ich mich recht entsinne, müsste es damit gehen:

private XmlDocument GetBaseDocument(string Filename, string Schema, string Stylesheet, string RootTag)
		{
			System.IO.Stream OutputTarget = new System.IO.FileStream(Filename,System.IO.FileMode.Create);
			XmlTextWriter Writer = new XmlTextWriter(OutputTarget,System.Text.Encoding.UTF8);
			Writer.Formatting = Formatting.Indented;
			
			Writer.WriteProcessingInstruction("xml","version=\"1.0\" encoding=\"utf-8\"");
			if (Stylesheet.Length>0) Writer.WriteProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"" + Stylesheet + "\"");
			Writer.WriteStartElement(RootTag);
			Writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
			Writer.WriteAttributeString("xsi", "noNamespaceSchemaLocation", null, Schema);
			Writer.WriteEndElement();
			Writer.Flush();
			Writer.Close();			
			XmlDocument doc = new XmlDocument();
			doc.Load(Filename);
			return doc;
		}

Bart Simpson

31.05.2007 - 21:03 Uhr

Du solltest die aktuellen MDACKomponenten installieren.

Bart Simpson

P.S. Für Zugriffe auf Access würde ich aber nicht ODBC, sondern OLEDB verwenden...

31.05.2007 - 20:58 Uhr

Das geht mit Left Outer Join:


SELECT * FROM Tab1 
LEFT OUTER JOIN Tab2
ON Tab1.Spaltenname1 = Tab2.Spaltenname2 
WHERE Tab2.Spaltenname2 IS NULL

Bart Simpson

17.04.2007 - 11:36 Uhr

Original von herbivore
wenn du die Properties in den einzelnen Spalten einer Datenbanktabelle ablegst, dann kannst du doch genau das tun. Ich denke, die Vorstellung dass eine Datenbank letztendlich ja alles auch nur in Dateien speichert, ist nicht hilfreich. Denn obwohl sie das tut, bietet sie doch viel mehr als als das reine Speichern von Daten in Dateien, um nur mal das offenkundigste zu nennen: SQL und ACID.

Ich denke, wir reden hier aneinander vorbei: Mir ist die Thematik rund um DB's ACID und was so alles dazu gehört sehr gut bewusst - was ich damit sagen wollte ist lediglich, dass ich damit keine "direkte" Möglichkeit zum Bearbeiten der Daten habe, sondern nur die "Systemeigenen", z.B. den Enterprise Manager des SQL Servers.

Damit ist es natürlich durchaus sehr einfach möglich die Werte in einer Tabelle zu editieren - solange eben alles auch in den Spalten "einzeln" abgelegt ist.
Das funktioniert aber nur dann, wenn ich vorher weiss, wie meine Daten genau aussehen -> Änderungen zur "Laufzeit" sind nicht möglich, oder ziehen strukturelle Änderungen in der DB nach sich.

Wobei ich mich hierbei hauptsächlich auf die Problematik von "Klassen-Hierarchien" (also Klasse B erbt von A und erweitert diese um neue Properties) beziehe - oder gibt's da 'ne schöne Möglichkeit das abzubilden?

Bart Simpson

17.04.2007 - 09:24 Uhr

Erst mal Danke für die Antworten - da sind doch schon mal ganz interessante Sachen dabei.

Zum Thema O/R Mapper bzw. OO-DB's: Ich gebe zu, ich hab mich noch nicht "tiefer" mit der Materie beschäftigt, kenne aber durchaus die Möglichkeiten und Grenzen.
Ich kann da für meinen Anwendungsfall aber keinen "deutlichen" Vorteil erkennen. Letztendlich wird alles wiederrum irgendwie in Files abgelegt (ob nun in 'ner DB oder sonstwo), die ich nicht direkt bearbeiten kann - aber genau das möchte ich.
Aber bitte korrigiert mich, wenn ich mich da irre 😉

@herbivore:
a) Werden meine Datenmengen wohl nicht "so groß" sein (hoff' ich jedenfalls, denn im wesentlichen handelt es sich um Konfigurationsdaten und Strukturinformationen meiner eigentlichen Daten)
-> Wo würdest Du denn da die Grenze ziehen, ab wann das sinnvoll sein kann oder zu "blödsinnig" ausartet?

b) Die Idee mit den versch. Tabellen hatte ich auch, allerdings ist der Ansatz für mich unpraktikabel: Ich werde einiges an Basis- und davon abgeleiteten Klassen haben. Zusätzlich soll das Ganze möglichst flexibel bleiben, also bei Bedarf relativ leicht auch mal um eine weitere Klasse erweiterbar sein.
-> Gibt's da evtl. andere Ansätze oder bin ich hier vielleicht "Betriebsblind" für die naheliegenste Lösung???

Bart Simpson

16.04.2007 - 20:53 Uhr

Ich denke grad darüber nach, wie ich in der Zukunft ein paar recht "komplexe" Datenstrukturen in irgendeiner Form abspeichern soll - deshalb würde mich mal interessieren, wie Ihr das denn so macht...

Konkretes Beispiel:
-Ich hab einen Satz von Klassen, die im Prinzip eine hierarchische Struktur abbilden. -Jede der Klassen hat dabei einen eigenen und für sie spezifischen Satz an Parametern (sprich: Properties).
-Jede einzelne (und auch die ganze Struktur) sind prinzipiell serialisierbar

Es soll nun folgendes relativ leicht möglich sein:

  • Das eigentliche Laden & Speichern der Daten
  • Das Kopieren und/oder Verschieben von Teilbereichen der Struktur(en)
  • Das manuelle Editieren von Konfigurationsdaten (weil es eben in der Entwicklungsphase noch keinen oder noch keinen vollständigen Editor geben wird)

Folgende Ansätze hab ich schon "durchdacht" bzw. ausprobiert:
1.) Die Struktur wird in einer SQL-DB abgelegt, wobei die Hierarchie über Parent- / Child-Referenezen dargestellt werden, und die eigentlichen "Daten" via XML Serialisierung in ein BLOB Feld gespeichert werden.
Vorteil: * Abfragen in SQL sind möglich (was auch kopieren und verschieben
ermöglicht
* Alle Daten sind zentral gespeichert und können zentral gepflegt werden
Nachteil: * Das einfache Editieren ist nicht wirklich möglich (oder zumindest sehr umständlich)

2.) Die Struktur wird in "irgendeiner" Form via XML-Serialisierung im Filesystem abgelegt.

Vorteil: Leicht manuell zu editieren, zu kopieren und zu verschieben
Nachteil: Die Vorteile von 1.) gibt', nicht...

Was haltet Ihr davon? Gibt's bessere Wege? Erfahrungen?

Bart Simpson

07.04.2007 - 11:29 Uhr

Das geht nur mit einem SELECT - also wiederrum einem normalen Command, das via ExecuteScalar ausgeführt wird.

Bart Simpson

02.04.2007 - 11:55 Uhr

Original von Azuuubiiiii
Ja und das mache ich ja (falls ich mich nicht irre) so:

using System.ServiceProcess;  

Du verstehst da was falsch... Die using Direktive bindet keinerlei Referenz auf die Assembly ein - das ist quasi nur eine "Abkürzung", damit Du nicht jedesmal im Quellcode System.ServiceProcess.KlasseXY schreiben musst, sondern einfach nur KlasseXY. Aber Du musst trotzdem immernoch die Referenz setzen - sonst "kennt" der Compiler die Assembly nicht...

Was Du machen musst, ist (in Visual Studio) folgendes: Klick im Solution- (bzw. deutsch: Projektmappen-) Explorer mit rechts auf das Projekt und dann auf Add Reference bzw. Verweis hinzufügen.

Im erscheinenden Dialog die Seite .net auswählen und dann auf System.ServiceProcess klicken. -> OK.

Bart Simpson

27.03.2007 - 20:49 Uhr

Wenn Dein "Teilstring" nur aus einem Zeichen besteht, dann geht's auch bequemer:

int count = String.Split('-').Length-1;

Bart Simpson

26.03.2007 - 20:34 Uhr

Du musst in Deinem Projekt eine Referenz auf System.ServiceProcess hinzufügen, dann sollte es gehen.

Bart Simpson

13.03.2007 - 23:18 Uhr

Ein wenig OffTopic, aber ich sag's immer wieder gern:

Um Pfade zusammen zu basteln gibt's Path.Combine - das erspart Ärger... 😉

Bart Simpson

21.02.2007 - 20:48 Uhr

Das ist aber im Prinzip identisch mit dem Vorschlag von Tom, nur dass er OR's nutzen würde...

Bart Simpson

16.02.2007 - 20:11 Uhr

Original von DeveloperX

SELECT * FROM Tabelle WHERE Replace(Name, 'ü', ue) = Replace('Müller', 'ü', ue)  

Sowas in die Richtung hab ich mir auch überlegt, aber dann müsste ich die Daten quasi dupliziert in einer "Such-Spalte" speichern (was ein ziemlich hohes Datenvolumen bedeuten würde), denn ein dynamisches Replace über >40 Mio. Datensätze ist kein Spass 😉

Bart Simpson

16.02.2007 - 18:21 Uhr

Der _ als Platzhalter steht aber doch immer für genau ein Zeichen...
D.h. M__ller findet zwar Mueller, aber nicht Müller weil zu wenige Zeichen.

Bart Simpson

16.02.2007 - 15:05 Uhr

Original von Tom
Weil es wird ja wohl nicht vorkommen das ü und ue gemischt sind in deinem Datenbestand.

Tja, wenn dem mal so wäre... Wie gesagt es sind Daten aus "Altbeständen"....

Bart Simpson

16.02.2007 - 11:39 Uhr

An SOUNDEX und Konsorten hab ich auch schon gedacht - ist aber zu unscharf. Da krieg ich dann u.U. viel zu viele Ergebnisse, was das Arbeiten sehr erschwert.

Die Variante mit dem OR hatte ich ebenfalls schon im Blick, aber die folgenden Nachteil:
Wenn mehr als ein Umlaut drin ist, dann muss man (eingentlich) alle Variationen per OR erlauben - dass sowas vorkommt ist zwar zugegebnener Maßen unwahrscheinlich, aber es geht ja ums Prinzip 😉

Die Schulung der Mitarbeiter... hmm das wäre ein Ansatz. Aber wie sagt ein Kollege von mir doch immer so treffend: "They can always built a better idiot!" 😁

Was mir noch einfiele, womit ich aber bisher keinerlei Erfahrung hab: Wie sieht's da mit 'ner Volltextsuche aus?

Bart Simpson

16.02.2007 - 00:06 Uhr

Ich kämpfe mich derzeit durch ein Problem wie ich am besten eine effiziente (sprich: schnelle) Suche in einer größeren DB machen soll:
Im wesentlichen hab ich dabei eine Tabelle mit Kundendaten (>40 Mio. Datensätze). Nun soll der User nach bestimmten Kunden "suchen" können und gibt dafür verschiedene Parameter an. Das ist solange kein Problem, solange keine Umlaute vorkommen...

Leider ist der Datenbestand aus Altbeständen übernommen, weshalb oft z.B. ein Herr Müller als Mueller eingetragen ist. Nun stellt sich die Frage: "Wie suche ich nach dem?" 🤔

Ich hab schon ein paar Ansätze durchgedacht, aber keinen wirklich guten gefunden - Irgendwelche Vorschläge?

Bart Simpson