Laden...

Hilfe bei LINQ SQL Abfrage

Erstellt von #coder# vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.264 Views
#coder# Themenstarter:in
395 Beiträge seit 2008
vor 13 Jahren
Hilfe bei LINQ SQL Abfrage

Hallo, ich möchte mit LINQ auf eine Datenbank eine Abfrage starten, diese soll alle vorkommenden strings aus einer Spalte liefern.
DB: **MyData **-> Table: **Posts **-> Spalte: Title

Nun hab ich folgendes Gerüst:

string text = "Haus";

string connectionString = ConfigurationManager.ConnectionStrings["BlogEngine"].ConnectionString;

            using(SqlConnection connection = new SqlConnection(connectionString))
            {
                try
                {
                    connection.Open();
                   
                    //var results = ABFRAGE  suche in Title nach dem vorkommen von text
                }

Wie würde die abfrage aussehen, und was nehme ich als Quelle??

5.299 Beiträge seit 2008
vor 13 Jahren

was soll das bringen? Angenommen, es existieren 5 Title "Haus", dann erhälst du 5 mal "Haus" zurück - und?

edit: mit Linq kann man keine Abfrage an eine Datenbank starten, das geht nur mit SQL. mit Linq kannst du einen DataContext abfragen (der dann intern eine SQL-Query generiert und abschickt)

Ühaupt sollte man m.E. bei der Datenbankprogrammierung nicht direkt in die DB grabschen, sondern eine der beiden Adapter-Technologien verwenden: OR-Mapper, (zb. LinqToSQL-DataClasses oder Entity-Framework) oder Dataset.

Bei diesen Technologien sind auch Tools enthalten, mit denen du die Abfrage schneller und sicherer konfigurierst, als handgecodet.

Aber wenn handgecodet, dann mit parametrisierten Abfragen (was rel. aufwändig ist), gugge [Artikelserie] Parameter von SQL Befehlen .

Wie gesagt: die beiden AdapterTechnologien arbeiten von Haus aus parametrisiert.

Der frühe Apfel fängt den Wurm.

#coder# Themenstarter:in
395 Beiträge seit 2008
vor 13 Jahren

Hab es nun so gelöst:


try
                {
                    connection.Open();
                    DataTable table = new DataTable();
                    
                    SqlDataAdapter adapter = new SqlDataAdapter("Select Title FROM be_Posts", connection);
                    adapter.Fill(table);

                    var result = from dt in table.AsEnumerable()
                                 where dt.Field<string>("Title").ToLower().Contains(prefixText)
                                 select dt;

                    foreach (DataRow row in result)
                    {
                        list.Add(row["Title"].ToString());
                    }

                    return list.ToArray();
                }

Gibt es Verbesserungsvorschläge?

R
68 Beiträge seit 2010
vor 13 Jahren

Hallo, ich möchte mit LINQ auf eine Datenbank eine Abfrage
starten, diese soll alle vorkommenden strings aus einer Spalte liefern.
DB: **MyData **-> Table: **Posts **-> Spalte: Title

Wenn Du mit einer SQL-Connection direct eine query an die DB senden willst,
könnte das grundsätzliche Gerüst so aussehen:


class Program
    {
        static void Main(string[] args)
        {

            string connString = @"..................................";
            SqlConnection SQLConnection = new SqlConnection();

            try
            {
                SQLConnection.ConnectionString = connString;
                SQLConnection.Open();
            }
            catch (Exception Ex)
            {
                if (SQLConnection != null)
                    SQLConnection.Dispose();

                Console.WriteLine("Fehler...");
                return;
            }

            string SQLStatement = "SELECT TOP 10 * FROM SHOP_KUNDEN_STAMM";

            SqlDataAdapter SQLDataAdapter = new SqlDataAdapter(SQLStatement, SQLConnection);
            DataTable dtResult = new DataTable();

            SQLDataAdapter.Fill(dtResult);

            foreach (DataRow drRow in dtResult.Rows)
            {
                Console.WriteLine(drRow["KUNDEN_NACHNAME"].ToString().Trim() + ", " + drRow["KUNDEN_VORNAME"].ToString().Trim());
            }

            SQLDataAdapter.Dispose();
            SQLConnection.Close();
            SQLConnection.Dispose();
        }
    }

Ob man direkt auf die DB zugreifen soll, bin ich persönlich etwas hin- und
hergerissen. Ich kenne die Mächtigkeit von SQL und die Möglichkeiten, bin
aber noch zu wenig in der LINQ-Thematik drin, um beurteilen zu können, dass
damit alle bzw. zumindest die meisten Möglichkeiten von SQL abgebildet werden
können.

Für LINQ-SQL, LAMDA & Co. gibts hier ein gutes Tutorial:
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx

Robin

R
68 Beiträge seit 2010
vor 13 Jahren

Gibt es Verbesserungsvorschläge?

Ja. Ich würde entweder alles in ein SQL-Command packen oder alles
via LINQ bzw. über einen DataContext abhandeln. Zuerst einen direkten SQL-
Command absetzen und auf dieses resultset wieder eine Query zu starten halte
ich nicht für optimal.

Robin

#coder# Themenstarter:in
395 Beiträge seit 2008
vor 13 Jahren

Bin auch deiner Meinung wegen dem DataContext mit LINQ, denn ich möchte nicht jedesmal die Datenbank öffnen für die Query. Ich brauche eine Mechanismus ala Cache welche alle 30min oder 60min, die Daten in den Cache aktualisert. Es wird immer der DataContext verwendet.
Wie wird sowas realisiert, ist das viel Aufwand?

5.299 Beiträge seit 2008
vor 13 Jahren

Gibt es Verbesserungsvorschläge?

schließe mich meinem vorredner an. Es handelt sich sogar um 3 abfragen:

  1. das sql-command
  2. die linq-query von der untypisierten datatable
  3. das foreach über die query - na gut, die query wird ja erst im foreach aufgelöst.

Vor allem bestätigt sich mein erster einwand: du erhältst eine List<string>, wo mw 5 mal "Haus" drin steht - da hättest du besser per sql den Count aller Datensätze mit "Title='Haus'" abgefragt.

und du hast keine typisierten Datenobjekte, wies Entities oder typisierte DataRows sind. mit sowas kommt man nicht sehr weit, weil man äpfel und birnen bei jeder Verwendung mittels cast und string-index explizit auseinanderdividieren muß, was bei typisierten objekten dir der compiler korrekt vorgibt.
ohne die compiler-vorgaben kannst du endlos fehler einbauen, die dann erst zur laufzeit auftreten, und auch nur, wenn das entsprechende element tatsächlich verarbeitet wird.

Überhaupt binnich bei der datenbänkerei gar nicht für Linq. Weil linq-abfragen immer nur ein IEnumerable liefern, kann man aus diesen Datenmengen nichts rauslöschen, und auch keine Datensätze anfügen.
Dagegen eine typisierte DataTable bringt ihre Add-Methoden mit, mit Datarow.Delete() ist der Datensatz entfernt, und mit TableAdapter.Update() werden alle geänderten Datarows (nur die!) einer DataTable in die DB geschrieben.

ah, jetzt kommt dein post dazwischen. Naja, der Datacontext cachet nicht, wohl aber das typisierte Dataset.

edit: guggemal "Datenbank in 10 Minuten" auf Movie-Tuts

Der frühe Apfel fängt den Wurm.

R
68 Beiträge seit 2010
vor 13 Jahren

Bin auch deiner Meinung wegen dem DataContext mit LINQ,
denn ich möchte nicht jedesmal die Datenbank öffnen für die Query. Ich brauche
eine Mechanismus ala Cache welche alle 30min oder 60min, die Daten in den
Cache aktualisert. Es wird immer der DataContext verwendet.
Wie wird sowas realisiert, ist das viel Aufwand?

Sofern ich das Thema überblicke, gibt es zwei Möglichkeiten:

  1. Über LINQ. Dazu schau Dir bitte die Beispiele an, die ich Dir bei meiner Antwort
    verlinkt habe. Dort werden verschiedene LINQ-Möglichkeiten mit Query- und
    LAMDA-Syntax beispielhaft erklärt.

  2. Der Vorschlag von ErfinderDesRades mit dem typisierten Dataset. Dieser ist
    vermutlich noch eleganter und besser geeignet. Mehr Infos dazu habe ich hier
    gefunden: http://msdn.microsoft.com/de-de/library/bwy42y0e(v=VS.100).aspx
    Hier wird aber auch zuerst direkt auf die DB via SQL-Command zugegriffen.
    Persönlich halte ich das für besser, da Du dadurch die Möglichkeiten von SQL
    direkt im Zugriff hast.

Robin

5.299 Beiträge seit 2008
vor 13 Jahren

Größter Nachteil der von dir im letzten Link gezeigten Vorgehensweise ist, dass das mit hohem Aufwand gebildete Dataset immer noch untypisiert ist.
Und untypisierte Datensätze sollte man auf keinen Fall programmieren, das ist wie wenn einer alle Variablen als object deklariert - da musser auch für jeden Zugriff casten. Ist sogar schlimmer, weil bei untypisierten DataRows muß nicht nur jeder Zugriff gecastet werden, ausserdem muß auch per string-Schlüssel die richtige Spalte angegeben werden (Schreibfehler!).

"Auf keinen Fall" ist etwas übertrieben. Wenn man was generisches auf der Pfanne hat, was also in allen typisierten Datasets mehrfach verwendbar sein soll, nimmt man natürlich die Basisklasse. ZB. habichmir einen DataAdapter-Konfigurator gebastelt, der anhand der im Dataset angelegten Spalten sich für Standard-Abfragen seine SqlCommands selbst generiert, sowas.

Aber wenn man dann wirklich die Anwendungslogik auflegen will, und Kunde-Datensätze mit BestellungDatensätze verknüppern, etc, da findich das ungefähr so übel wie das böse GoTo, wenn da alle Kunde-Eigenschaften und alle Bestellung-Eigenschaften immer nur als object vorliegen.

Dagegen hat man mit den Designern in minutenschnelle ein fehlerfreies typisiertes Dataset generiert, inkl. passender TableAdapter, wofür man per Hand schnell mal mehrere hundert Codezeilen zu schreiben hätte.

Und weil die Typisierung schon zur Designzeit festgelegt ist, kann man dann auch im FormDesigner Databindings einrichten, etwa ein Datagridview mit allen Spalten bildschön und maximal sicher gestalten, wofür man von Hand wiederum zig Zeilen zu coden hätte. Ich verweise nochmal auf meine Movie-Tuts.

Ach guck, inhaltlich sind meine Tuts durchaus vergleichbar der Vorgehensweise von deinem ersten Link, da werden ja auch designergestützt typisierte Entities erstellt (ähnlich DataBindingfähig wie typ.datasets).
Nur bauen meine Tuts aufs Dataset auf, und die LinqToSql-Classes auffm DataContext.
Das sind halt die beiden Technologien, die zur Verfügung stehen.

Der frühe Apfel fängt den Wurm.