2009-02-23 8 views
18

Ich werde wahrscheinlich für die Portierung einer vb6-Anwendung auf C# verantwortlich sein. Diese Anwendung ist eine Windows-App, die mit einer Zugriffs-DB interagiert. Der Datenzugriff ist in Basisgeschäftsobjekten gekapselt. Eine Klasse für einen Tisch im Grunde genommen. Die vorhandenen vb6-Business-Objekte lesen und schreiben über DAO in die DB. Ich habe DALs und ORMs schon ein paar Mal geschrieben, aber alle waren auf SQL Server ausgerichtet. Dieser muss auf den Zugriff und den SQL Server ausgerichtet sein. In früheren Projekten würde ich die SQL-Zeichenfolgen in den privaten Teilen des Geschäftsobjekts platzieren und den redundanten SQL-Code möglicherweise wie das Verbinden, Erstellen eines Befehls in eine gemeinsame Basisklasse verschieben, um den Code zu reduzieren.Wo setzen Sie SQL-Anweisungen in Ihre C# -Projekte?

Diesmal denke ich über das Schreiben der SQL-Zeichenfolgen in eine .settings-Datei oder eine andere Schlüssel/Werttyp-Textdatei. Ich würde dann ein SQL-Dienstprogramm schreiben, um diese Datei zu bearbeiten und mir erlauben, die parametrisierten Abfragen auszuführen und zu testen. Diese Abfragen werden im Geschäftsobjekt anhand des Namens referenziert, anstatt den SQL-Code in Code einzubetten.

Ich weiß, dass ein Standardansatz darin besteht, für jede Zieldatenbank eine DAL zu erstellen, und der Konfigurationsstatus anzugeben, welche DAL zu verwenden ist. Ich möchte wirklich nicht die zwei DAL-Klassen für jede Datenbank erstellen. Es scheint, als wäre es weniger Code, wenn ich nur die korrekte Abfrage nach Schlüsselname referenziert hätte und den richtigen Verbindungstyp hätte.

Also, macht ihr Jungs so etwas? Wie würden Sie dieses Problem angehen? Was funktioniert am besten für Sie?

Danke!

Antwort

24

Nun, es gibt viele Möglichkeiten - so dass es hängt wirklich davon ab, was Ihre dringendsten Bedürfnisse sind :-)

Ein Ansatz Möglicherweise müssen Sie SQL-Anweisungen als Textdateien in Ihrer VS-Lösung erstellen und sie als "eingebettete Ressource" in der "Build-Aktion" markieren. Auf diese Weise wird die SQL in der resultierenden Anordnung enthalten und kann von ihm zur Laufzeit mit dem ResourceManifestStream von .NET Framework abgerufen werden:

private string LoadSQLStatement(string statementName) 
{ 
    string sqlStatement = string.Empty; 

    string namespacePart = "ConsoleApplication1"; 
    string resourceName = namespacePart + "." + statementName; 

    using(Stream stm = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) 
    { 
     if (stm != null) 
     { 
      sqlStatement = new StreamReader(stm).ReadToEnd(); 
     } 
    } 

    return sqlStatement; 
} 

Sie müssen „ConsoleApplication1“ mit Ihrem tatsächlichen Namensraum ersetzen, in denen Die SQL-Anweisungsdateien befinden sich. Sie müssen sie anhand des vollständig qualifizierten Namens referenzieren. Dann können Sie Ihre SQL-Anweisung mit dieser Zeile laden:

string mySQLStatement = LoadSQLStatement("MySQLStatement.sql"); 

Dies macht jedoch die Abfragen eher "statisch", z. Sie können sie zur Laufzeit nicht konfigurieren und ändern - sie sind direkt in die kompilierten binären Bits eingebettet. Auf der anderen Seite haben Sie in VS eine saubere Trennung zwischen Ihrem C# -Programmcode und den SQL-Anweisungen.

Wenn Sie in der Lage sein können, möglicherweise zwicken und ändern sie zur Laufzeit, würde ich sie in eine einzige SQL-Tabelle, die z. ein Schlüsselwort und die eigentliche SQL-Abfrage als Felder. Sie können sie dann bei Bedarf abrufen und ausführen. Da sie sich in der Datenbanktabelle befinden, können Sie sie auch nach Bedarf ändern, korrigieren oder ändern, ohne die gesamte App neu bereitstellen zu müssen.

Marc

+1

Ich habe diesen Ansatz verwendet und ich mag es. Im Gegensatz zu den meisten Leuten bin ich nicht damit einverstanden, während der Laufzeit Code ändern zu können, sogar einfache SQL-Anweisungen, daher ist die Tatsache, dass er mit der Assembly kompiliert wird, ein Vorteil für mich. – Chris

+1

Freut mich zu hören, dass dieser Ansatz von anderen genutzt und begrüßt wird! :-) Und ich stimme zu - manchmal Back Sachen in Ihre kompilierten Bits ist ein Plus. –

+3

Verwenden Sie anstelle von namespacePart this.GetType(). Namespace für die aktuelle, dynamische Version und typeof (Program) .Namespace für static. Natürlich, wenn Sie es in die Programmklasse als statisch setzen. Vergessen Sie nicht, wenn Ihre SQL-Datei im SQL-Verzeichnis ist, beziehen Sie sich darauf durch "SQL.StatementName.sql" – Harry

1

Ich werde sagen, wo ich es nicht jemals setzen werde, etwas, was ich gesehen habe in etwas Code ich geerbt getan. Es war in Java, sondern gilt für jede Sprache

  • Eine Basisklasse, die statischen Elementvariablen für SQL-Anweisungen geschützt erklärt, inited auf null, mit einer get-Methode, die einzelne SQL-Anweisungen gibt

  • A Unterklasse für jeden unterstützten Datenbankserver mit einer init-Methode, die Membervariablen

  • Mehrere DA Klassen, die die Basisklasse Methode verwenden, um die Basisklasse zuordnet SQL-Anweisungen zum abrufen

  • Die Anwendung Start-up-Klasse mit der Verantwortung für das richtige Unterklasse-Objekt erstellen und seine Init-Methode

Ich werde auch nicht in zu erklären, warum ich das überhaupt :-)

tun werde nicht gehen rufen
+2

OO puristische Sprache verursacht OO Alpträume so! komisch! – Steve

1

Eine von uns verwendete Methode ist eine Klasse, die eine Verbindung mit der DB und Methoden zum Aufrufen von Prozeduren herstellt, und im Methodenparameter würden Sie den Prozedurnamen angeben. Also ist der gesamte SQL-Code in der Prozedur. wir würden Überlastungen für die unterschiedlichen Rückgabetypen

class ConnectToSQL() 
{ 
     //connectSql code (read from setting file i assume) 

     XMLDataDocument runProcedure(string procedureName); 
     int runProcedure(string procedureName); 

     //etc.... 
} 
+0

Sie können keine Überladungen haben, die sich nur durch Rückgabetyp unterscheiden - es wird einen Compilerfehler geben CS0111 – MattDavey

2

LINQ to DataSet klingt wie die Art und Weise für Sie gehen verwenden.

Wenn Sie .NET 3.5 vor/LINQ noch nicht verwendet haben, dann sind Sie auf der Suche nach einem Leckerbissen. LINQ speichert Sie Ihre Raw-SQL in Zeichenfolgenliteralen und bietet Ihnen eine logischere Möglichkeit zum Erstellen von Abfragen.

Wie auch immer, diesen Link Check-Out für LINQ auf Access-Datenbanken - http://msdn.microsoft.com/en-us/library/bb386977.aspx

9

Wenn ich es wirklich brauchen, habe ich die Abfragen in einzelne * SQL-Dateien, sie dann in Resources.resx umfassen. Es gibt einen Abschnitt "Dateien", in dem Sie eingebettete Ressourcendateien einschließen können.

Danach kann ich generierte Resources.MyQuery-Eigenschaft verwenden, die beide garantiert, dass Ressource vorhanden ist und speichert mir eine benutzerdefinierte Ressource laden Methode.

+0

Ich mag diese Lösung auch. Die generierten Eigenschaften sind praktisch. – Steve

1

Wenn ich eine Anwendung für SQL und Access erstellen müsste, würde ich eine IDAL-Schnittstelle verwenden, DALCommon mit gemeinsamer Funktionalität Implementierung und separate DALSql und DALAccess, geerbt von DALCommon, mit bestimmten Dingen, wie Ausnahmen, Transaktionen Handhabung, Sicherheit usw.
Ich habe gespeicherte Prozedurnamen oder Abfragen in Ressourcendateien gespeichert.

0

Manchmal müssen Sie, wie bei benutzerdefinierten Reporting-Apps, die Impedanzübereinstimmung berücksichtigen und dem SQL-Code besondere Bedeutung beimessen. In diesen Fällen empfehle ich Folgendes: Erstellen Sie für jedes Modul, das SQL-Strings enthält, eine einzige statische SQL-Klasse, um alle zu halten. Einige der SQL-Strings benötigen wahrscheinlich Parameter, seien Sie also konsistent und setzen Sie jeden String hinter seine eigene statische Methode.

Ich mache das nur für die gelegentliche benutzerdefinierte Berichterstattung App, aber es funktioniert immer gut und fühlt sich erfrischend und befreiend. Und es ist ziemlich nett, Monate später zu kommen, um eine Verbesserung zu machen und das gesamte SQL, das auf Sie wartet, in einer einzigen SQL.cs-Datei zu finden. Wenn man nur diese eine Datei liest, kommt alles zurück und oft ist dies die einzige Datei, die geändert werden muss.

Ich sehe keine Notwendigkeit in diesen Fällen zum Ausblenden der SQL in Ressourcen oder anderswo. Wenn SQL wichtig ist, dann ist es wichtig. Interessanterweise mischen nun immer mehr Entwickler SQL frei mit C#, einschließlich dieser Site, weil LINQ im Wesentlichen das ist.

Schließlich, wie immer, stellen Sie sicher, dass Sie nicht anfällig für SQL-Injection-Angriffe sind. Insbesondere wenn Benutzereingaben beteiligt sind, stellen Sie sicher, dass Sie eine Art von Parametrisierung verwenden und dass Sie keine String-Verkettung verwenden.

0

Die oben gezeigten Einbettungslösungen funktionieren möglicherweise nicht, wenn SQL Query eine "wo" Ursache hat, aber für die gleiche Abfrage benötigt der nächste Lauf PropertyID = '113', wenn die PropertyID eingelesen wird.

0

Glad you asked! Put your sql in a QueryFirst .sql template.

Es ist automatisch in der App als eingebettete Ressource kompiliert, aber Sie kümmern sich nicht. Sie schreiben es einfach in ein echtes SQL-Fenster, das mit Ihrer Datenbank verbunden ist, mit Syntaxvalidierung und Intellisense für Tabellen und Spalten, und verwenden es dann über die generierten Methoden Execute() mit Intellisense für Ihre Eingaben und Ergebnisse.

Disclaimer: Ich schrieb QueryFirst.