Laden...

Linq to SQL: NULL in Datenbank übertragen

Erstellt von Jonas123 vor 10 Jahren Letzter Beitrag vor 10 Jahren 6.776 Views
J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren
Linq to SQL: NULL in Datenbank übertragen

verwendetes Datenbanksystem: < [Artikel] LINQ to SQL >

Hallo an alle!
Ich bin neu hier und bitte daher zuerst mal darum, dieses Thema an den richtigen Platz zu verschieben ..

Nun zu meinem Problem:

Ich habe eine Form mit mehreren Textboxen, die in meine Datenbank eingelesen werden sollen.
Insert und Update funktioniert alles wunderbar, allerdings möchte ich für nicht gefüllte Textboxen den Wert NULL in die Datenbank übergeben, sowohl bei Integern und Reals, als auch bei Strings.
Ich habe mir eine Methode gebastelt, mit der ich jede Texbox abfrage, ob sie einen Wert hat, oder nicht. Wenn nicht, soll sie eben NULL zurückgeben.
Die sieht wie folgt aus:

public static string nullen (string x)
        {
            if (x == "")
            { return null; }
            else 
            { return x; }
        }

Es funktioniert allerdings nicht, es werden für Zahlentypen "0" und für Strings "" in die Datenbank eingelesen.

Kann mir jemand helfen?

PS.: man muss dazu sagen, dass ich gerade im ersten Lehrjahr bin und mir Fehler bitte noch zu verzeihen sind. 👅

2.207 Beiträge seit 2011
vor 10 Jahren

Hallo Jonas123,

erstmal sind, mMn "null"-Werte in der Datenbank mit Vorsicht zu geniessen. Bei String ist es noch vertretbar, ja, aber wenn man an defensives Programmieren denkt, ist es vielleicht gar nicht schlecht bei einer TextBox, wenn der Benutzer eben nichts eingegeben hat auch nichts ("" und nicht NULL) zu speichern. Beim Lesen musst du auch jedesmal auf NULL prüfen ==> Wuerdest du dir sparen. (String.IsNullOrEmpty erleichtert im konkreten Fall die Sache, ändert aber am Prinzip nichts)

Die Methode, die wir hier von dir sehen, bringt uns recht wenig. Kannst ja mal zeigen, wo du etwas abspeicherst.

Erlaubt die Datenbank überhaupt NULL-Werte in der Spalte?

Gruss

Coffeebean

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Hallo Coffeebean,

erstmal vielen Dank für eine Antwort.
Habe leider auch grade bemerkt, dass ich gar nicht dazu gesagt habe was ich der Methode übergebe..

Für das x wird jede einzelne TextBox übergeben und überprüft, ob sie gefüllt sind, oder nicht..
Ich arbeite mit mehr als 150 TextBoxen, das heißt, dass es schon recht aufwändig ist, vielleicht geht das ja auch alles einfacher? 😃

NULL soll es laut Chef sein, da es für die Auswertung relevant ist.

2.207 Beiträge seit 2011
vor 10 Jahren

Kannst ja mal zeigen, wo du etwas abspeicherst.

Erlaubt die Datenbank überhaupt NULL-Werte in der Spalte?

Gruss

Coffeebean

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Die Datenbank erlaubt Null-Werte, ja.
Was genau ich wo abspeichere? Meinst du mein Insert?

2.207 Beiträge seit 2011
vor 10 Jahren

Hallo Jonas123,

ja. Hast du mal mit dem Debugger überprüft, ob du auch null in die DB gibst bei deinem Insert?

Gruss

Coffeebean

F
10.010 Beiträge seit 2004
vor 10 Jahren

Vorallem hast du die Grundlagen von ADO.NET und von [Artikelserie] SQL: Parameter von Befehlen beachtet?

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Hallo alle..

das Insert in die Datenbank funktioniert alles, aber es werden eben nur bei Zahlentypen "0" und bei strings "" übertragen, nicht wie sonst, wenn ein Feld leer bleibt NULL.

edit: das übergeben muss zwangsläufig klappen, bzw. das übergeben meines "null" aus der Methode, da eine übergabe von "" bei zahlentypen einen Fehler hervorrufen würde.
Das Problem ist halt nur, dass er aus der "null" in der Datenbank die o.g. dinge macht, sprich "0" und ""..

G
141 Beiträge seit 2011
vor 10 Jahren

Hallo Jonas123,

Es wäre vielleicht noch wichtig deine Insert Methode zu kennen, wo du die Strings/Integer in die Datenbank schreibst. Vielleicht könnte dort schon der Fehler liegen.

Gruß
Gnozo

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Hallo Gnozo,

das Schma sieht in etwa so aus :


string insert;
insert = "INSERT INTO MeineTabelle";
insert += "(Feld1, Feld2, Feld3 .... )";
insert += "VALUES ('" + Tools.nullen(this.tb_1.Text) + "','" + Tools.nullen(this.tb_2.Text) + "','";
insert += Tools.nullen(this.tb_3.Text) + .... + "');";

db1.ExecuteCommand(insert);

Die Methode "nullen" befindet sich in der Klasse "Tools" und sieht wie oben schon mal beschrieben so aus :


        public static string nullen (string x)
        {
            if (x == "")
            { return null; }
            else 
            { return x; }
        }

3.511 Beiträge seit 2005
vor 10 Jahren

Klarer Fall von [Artikelserie] SQL: Parameter von Befehlen

Hat übrigens FZelle auch schon gepostet. Scheinbar hast du dir den Link nicht angeschaut.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

G
141 Beiträge seit 2011
vor 10 Jahren

Das Problem ist, dass du dir dort einen String zusammen setzt. Wenn du dir dein Insert-String mal im Debugger ansiehst, steht dort nicht NULL sondern einfach nichts. Somit kommt in der Datenbank auch nichts an und es wird als "" abgespeichert und nicht als NULL.

In dem Artikel von FZelle wird das mit dem NULL-Statement erklärt.

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Danke für alle Antworten, ich sehe den Sinn klar und deutlich..
Leider bin ich wie gesagt noch anfänger.. könnte jemand mein Beispiel kurz auf die Parameter-Methode anwenden?

3.511 Beiträge seit 2005
vor 10 Jahren

Auch hier kann ich nur wieder auf den Link verweisen im 2. Abschnitt "Vorteile der Parameter-Lösung in der Praxis". Wenn du das durchgehst, bekommst du das schon selber hin.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

G
141 Beiträge seit 2011
vor 10 Jahren

Dieser Ausschnitt ist das wichtige daran:


if (firstName != null)
      sb.Append("'" + QuoteString(firstName) + ", ");
    else
      sb.Append(", NULL, ");

Selber auf deine Methode anwenden, kannst du aber sicher aleine 😃

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Da tun sich mir aber noch Fragen zu auf:
Wieso wird ein Integer in der der AddEmployee zurückgegeben? was wird damit gemacht?

  1. Sache: ich habe etwa 150 Textboxen, muss ich alle in den Übergabeparametern der Methode aufzählen?
G
141 Beiträge seit 2011
vor 10 Jahren

Wenn du die Textboxen selber zeichnest, kannst du sie mit einer schleife durchlaufen. Wie das bei Controls ist, die du mit dem Designer eingefügt hast, kann ich dir nicht sagen.

3.511 Beiträge seit 2005
vor 10 Jahren

Das int in der AddEmployee Methode gibt einfach nur die Anzahl der betroffenen Zeilen zurück, also das ExecuteNonQuery (steht aber in der MSDN).

ich habe etwa 150 Textboxen, muss ich alle in den Übergabeparametern der Methode aufzählen?

Ja 😃
Aber das durchlaufen der Controls ist ein guter Hinweis. Wobei hier natürlich noch die Trennung der UI und der Daten bedacht werden sollte.

@Gnozo: Dein geposteter Code Ausschnitt zeigt, dass du ebenfalls den Artikel nicht gelesen hast. Denn genau so macht man es nicht.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

okay, das ist aber nicht das größte problem, das wäre für mich machbar.. aber ich komme mit den anderen dingen nicht klar.

ich benutze keine SQLConnection sondern eine LinQtoSql klasse um die Verbindung zur Datenbank herzustellen.. was also ist der ConnectionString 🤔

3.511 Beiträge seit 2005
vor 10 Jahren

Wenn du mit Linq2Sql arbeitest (ist übrigens obsolete, nimm das Entity Framework, oder NHibernate, oder halt pur ADO.NET), müsstest du eh Entities haben die du direkt per Linq2Sql in die Datenbank ballern kannst.

Aber das geht jetzt definitiv in Richtung [Hinweis] Wie poste ich richtig? Punkt 1.1. Wenn du Linq2Sql weiter verwenden willst, dann schau dir bitte dazu weiterführende Dokumentationen an (MSDN, Google, etc...)

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

3.825 Beiträge seit 2006
vor 10 Jahren

Hallo Jonas,

mit ADO.NET-Bordmitteln ist Dein Vorhaben nicht so schwierig.

Alle Controls durchgehen und die Werte in ein Dataset schreiben. Dort kannst Du leere Felder mit null füllen.

Am einfachsten ist es wenn der Control-Name gleich dem Spaltennamen ist, oder schreib den Spaltennamen in das Tag des Controls.

Willst Du bei numerischen Feldern zwischen 0 und null unterscheiden ? Oder ist 0 = leer = null ?

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Hallo Bernd,
ich danke dir für deine Antwort.

Null soll Null sein und nicht 0. Das Programm soll eine Access Datenbank ersetzen, die die bisherige Tabelle immer mit Null gesetzt hat bei leeren Tboxen.

Könntest du mir ein kurzes Code-Beispiel geben von deiner Idee?

R
212 Beiträge seit 2012
vor 10 Jahren

ich denke er meint:


public static string nullen (string x)
        {
              return x == "" ? "null":x;  
        }

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Da habe ich aber wieder das Problem, dass das nur für strings funktioniert, bei zahlentypen wirft er mich raus. bzw sogar auch, wenn ein string/char nur für weniger als 4 zeichen ausgelegt ist.

16.835 Beiträge seit 2008
vor 10 Jahren

Es gibt keine Möglichkeit alle Arten abzudecken.
Im Endeffekt musst Du (Object, Nullable, Not-Nullable, struct etc... bzw. String, Int32, Int64..) eigene Routinen definieren.
Das ist auch üblich in gängigen Providern.

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Danke Abt, aber wie genau kann ich das machen? ich will ja auch in String-Feldern nicht den Wert "NULL" als string haben, sondern ein leeres Feld, welches in SQL als

[COLOR]NULL[/COLOR]

angezigt wird..

Ich habe meine Methode nochmal wie folgt überarbeitet:

public static object nullen (string x)
        {
            if (x == "")
            { return Convert.DBNull; }
            else
            { return x; }
        }

das wird ohne Probleme ausgeführt, aber NULL sind meine Felder in der Datenbank trotzdem nicht.

16.835 Beiträge seit 2008
vor 10 Jahren

Redest Du von DBNull, von null, oder von "Null".
Das sind alles 3 völlig verschieden Dinge - und alle 3 musst Du abdecken.

Definier für Dich, was leer bedeutet. Ich würde - aus Anwendungssicht - null wählen. Und nicht jedes DBMS versteht null gleich.
SQLite mag es als null speichern; irgendein Viewer von irgendeinem Hersteller macht "" daraus - damit der Anwender sieht es ist "leer" (obwohl es eben null ist). Andere DBSysteme - vor allem NoSQL-DB - gehen nochmals anders vor und arbeiten mit Platzhaltern. So wird null zu $csharpnull etc...

Definier für Dich also erstmal die konkreten Zustände und dann mach Dich ran an den Code.

3.825 Beiträge seit 2006
vor 10 Jahren

Hallo Jonas,

Könntest du mir ein kurzes Code-Beispiel geben von deiner Idee?

ja, ganz grob, ohne Gewähr :

DataSet ds = new DataSet();
DataRow rw = ...
foreach(string col in ds.Tables[0].Columns)
{
    string val = this.Controls[col].Text;
    if (rw[col].GetType() == typeof(System.String))		// column is string
    {
    	    if (val == "") rw[col] = null;
    	    else rw[col] = val;
    }
}

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Hallo Abt,

wir haben unsere Datenbanken auf einem Microsoft SQL Server.
Ich habe in C# versucht, null und DBNull zu übergeben, aber beides bewirkt im SQL dasselbe, nämlich, dass für Zahlentypen "0" und für Stringtypen "" angezeigt wird, statt das NULL, bei leeren Feldern.
Ich hoffe das war jetzt verständlich 😕

Danke Bernd.. 😃
ich werde das mal mit meinem Kollegen besprechen, vielleicht kann der mit dazu noch helfen.

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

So ich entschuldige mich an dieser Stelle schon mal für den Spam..
ich habe die Paramether-Methode jetzt in meinem Programm benutzt und bekomme folgende Fehlermeldung beim ExecuteNonQuery:
Falsche Syntax in der Nähe von 'nvarchar'.
Die @-Skalarvariable muss deklariert werden.

Ich muss dazu sagen, dass ich Felder habe, die mit Unterstrich verbunden sind und somit mit [] eingegrenzt werden.. ich vermute, dass hier der Fehler liegt.. ?
Was kann ich tun?

Codeschnipsel:

sb.AppendLine("VALUES (@[Feld_eins], usw..");

...

cmd.Parameters.AddWithValue("[Feld_eins]", this.tb_feldEins.Text ?? Convert.DBNull);
4.939 Beiträge seit 2008
vor 10 Jahren

Hallo Jonas,

der Parameter hat doch nichts direkt mit dem Spaltenname der Tabelle zu tun, den Parameternamen kannst du frei definieren (aber er sollte eben nur aus alphanumerischen Zeichen bestehen).

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Hallo Th69,

das heißt, ich kann alles frei definieren? auch nach den @'s?
Vielen dank 😃

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

Alsoooo...

der Insert mit der Parameter-Methode funktioniert jetzt ohne Probleme, danke an alle..

Leider ist mein eigentliches Problem, nämlich NULL in die Datenbank zu bekommen, immer noch nicht gelöst, er macht genau das gleiche wie vorher..

Dieses:

?? Convert.DBNull

Ende sollte das doch eigentlich erledigen, oder? 😦

4.939 Beiträge seit 2008
vor 10 Jahren

Der ??-Operator testet nur auf 'null', nicht auf String.Empty.
Nimm daher besser


String.IsNullOrEmpty(tb_feldEins.Text) ? Convert.DBNull : tb_feldEins.Text

J
Jonas123 Themenstarter:in
16 Beiträge seit 2013
vor 10 Jahren

es funktioniiiiiert! 😃
1000 Dank an alle hier!
Ich bin überglücklich 😉