Autor Beitrag
Bemalu
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Fr 10.06.11 15:50 
Hallo

ich arbeite unter Windows XP mit Microsoft SQL Server EXPRESS 2008 R2 und Visual C# 2010 EXPRESS. Nun habe ich ein sehr einfaches Beispielprogramm geschrieben, um die Datenbank zu Verbinden und ein paar Daten auszulesen:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace DatenbankTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void buttonBeenden_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void buttonDbZugriff_Click(object sender, EventArgs e)
        {
                      
            SqlConnection verbindung = new SqlConnection();
            SqlCommand befehl = new SqlCommand();
            SqlDataReader leser;

            verbindung.ConnectionString = "Data Source=.\\SQLEXPRESS;" +
               "AttachDbFilename=D:\\SQL-Server\\MSSQL10_50.SQLEXPRESS\\MSSQL\\DATA\\creasoft1_Data.mdf;" +
               "Integrated Security=True;Connect Timeout=30;User Instance=True";

            befehl.Connection = verbindung;
            befehl.CommandText = "SELECT TOP 10 * FROM adressen";


            try
            {
                verbindung.Open();

                leser = befehl.ExecuteReader();
               
                leser.Read();
                MessageBox.Show(leser["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);

                leser.Read();
                MessageBox.Show(leser["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);
                leser.Read();
                MessageBox.Show(leser["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);
                leser.Read();
                MessageBox.Show(leser["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);
                leser.Read();
                MessageBox.Show(leser["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);
                leser.Read();
                MessageBox.Show(leser["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);
                leser.Read();
                MessageBox.Show(leser["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);
                leser.Read();
                MessageBox.Show(leser["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);


                leser.Close();
                verbindung.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

    }
}


Dieser Code lässt sich genau einmal ausführen. Die Namen werden wie gewünscht ausgegeben und das Programm kann dann normal beendet werden. Dabei wird offenbar die Datenbank zerstört, denn das Programm lässt sich nur einmal ausführen. Will ich mit Management SQL Server Studio die Datenbank anschauen, ist dieses defekt und lässt sich nicht mehr verbinden. Die DB lassen sich auch nicht umbenennen oder löschen.

Dazu meine Fragen:

- Was ist falsch an meinem Programm, wodurch wird die DB zerstört ?
- Welche Möglichkeiten habe ich eine defekte DB zu reparieren ?
- Gibt es eine Möglichkeit defekte DB manuell zu löschen, welche Files muss ich löschen ?

Gundsatzfragen: Verbindet Ihr eigentlich vor jedem Datenbankzugriff neu mit der Datenbank oder verbindet man beim Starten und lässt die DB dann geöffnet ?

Vielen Dank für Eure Hilfe

Bema

Moderiert von user profile iconChristian S.: Code- durch C#-Tags ersetzt
Trashkid2000
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 561
Erhaltene Danke: 137



BeitragVerfasst: Sa 11.06.11 18:51 
Hallo,
hast Du denn schon rausgefunden, woran es liegt? Ist das DB-File denn wirklich zerstört?
Ich meine, kannst Du denn nach einem Neustart des Rechners wieder damit arbeiten?

Also ich kann das Problem nicht reprojizieren. Bei mir klappt es auf jeden Fall.
Aber mal eine Anmerkung zu Deinem geposteten Code:
1.: Verwende using-Blöcke, und Du spartst Dir das Close() bzw. das Dispose(). Ausserdem macht es das Ganze lesbarer, wie ich finde.
2.: Doppelter Code ist nie gut. Ich beziehe mich auf das 8x MessageBox.Show(...). Extembeispiel an dieser Stelle: Was, wenn Du 1000 Datensätze anzeigen lassen wollen würdest? Du verstehst, was ich meine!? Warum legst Du das nicht in eine Schleife? Also solange der reader was zu lesen hat? Erstens macht das den Code kürzer, besser änderbar und auch fehlerunanfäliger. Denn wenn es nur einen Datensatz in der Tabelle gibt, und Du liest einfach weiter, so knallt es an dieser Stelle.

So könnte der Code also aussehen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
 
string connString = 
@"Data Source=.\SQLEXPRESS;
AttachDbFilename=D:\SQL-Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA\creasoft1_Data.mdf;
Integrated Security=True;Connect Timeout=30;User Instance=True"
;
string selectStmt = "SELECT TOP 10 * FROM adressen";
        
try
{
  using (SqlConnection conn = new SqlConnection(connString))
  {
    conn.Open();
    using (SqlCommand cmd = new SqlCommand(selectStmt, conn))
    {
      using (SqlDataReader reader = cmd.ExecuteReader())
      {
        while (reader.Read())
        {
          MessageBox.Show(reader["name"].ToString(), "Nächster Datensatz", MessageBoxButtons.OK);   
        }
      }        
    }
  }
}
catch (SqlException ex)
{
  MessageBox.Show(ex.Message);
}
LG
Bemalu Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: So 12.06.11 16:14 
Hallo Marko

vielen Dank, dass Du Dich meiner angenommen hast. Natürlich hast Du Recht bezüglich der While-Schleife, ich hatte sie nur weggelassen, weil ich sicher gehen wollte, dass ich nicht über den letzten Datensatz hinauslese.

Leider bringt Deine Programmversion keine Abhilfe. Ich erzähle Dir mal was passiert:

Zuerst setze ich im SQL Server Management Studio ein paar SELECT Befehle ab, damit ich sicher bin, dass die DB unbeschädigt ist. Die DB hat 5 Tabellen mit je ca. 300'000 Datensätzen. Es funktioniert alles bestens. Nun schliesse ich Management Studio und starte Visual C# Studio. Lade Deinen Code und führe ihn aus. Es erscheinen nacheinander 10 MessageBoxen mit jeweils einem Namen aus der Datenbank. Soweit funktioniert also alles.

Doch wenn ich nun die Applikation beende und nochmals neu starte kommt eine Fehlermeldung (siehe PDF oben). Auch im Studio Manager lässt sich die DB nicht mehr benutzen. Siehe zweite Fehlermeldung im PDF. Die Datenbank lässt sich erst nach einem Neustart des Rechners Wiederherstellen.

Fehlermeldungen als PDF

Es sieht also so aus, wie wenn die C#-Applikation die DB zerstören würde. Das weckt natürlich nicht gerade mein Vertrauen in C# aber vielleicht hast DU noch eine Idee ...

Vielen Dank.

Bema
stendate
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19
Erhaltene Danke: 1



BeitragVerfasst: So 12.06.11 16:35 
user profile iconBemalu hat folgendes geschrieben Zum zitierten Posting springen:

Zuerst setze ich im SQL Server Management Studio ein paar SELECT Befehle ab, damit ich sicher bin, dass die DB unbeschädigt ist. Die DB hat 5 Tabellen mit je ca. 300'000 Datensätzen. Es funktioniert alles bestens. Nun schliesse ich Management Studio und starte Visual C# Studio. Lade Deinen Code und führe ihn aus. Es erscheinen nacheinander 10 MessageBoxen mit jeweils einem Namen aus der Datenbank. Soweit funktioniert also alles.

Doch wenn ich nun die Applikation beende und nochmals neu starte kommt eine Fehlermeldung (siehe PDF oben). Auch im Studio Manager lässt sich die DB nicht mehr benutzen.


Ich hab ne Vermutung, du übergibts im Connection-String das Schlüsselwort AttachDbFilename, obwohl die Datenbankdatei creasoft1_Data.mdf offenbar bereis in der SQL-Server Instanz eingehangen ist, da du ja im Schritt 1 per Management-Studio darauf zugegriffen hast.

ausblenden C#-Quelltext
1:
AttachDbFilename=D:\SQL-Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA\creasoft1_Data.mdf;					


Ich bin mir jetzt nicht sicher ob man das so machen sollte. Du könntest 2 Dinge ausprobieren:

1) Die Datenbank nach verwendung im Management-Studio explizit wieder aushängen.

2) Ein Connetion-String verwenden der voraussetzt, dass die Datenbank im Server vorhanden ist:

ausblenden C#-Quelltext
1:
Server=.\SQLEXPRESS;Database=creasoft1_Data;Trusted_Connection=True;					


Weitere Varianten der Connection-Strings gibt es unter [1].


[1] connectionstrings.com/sql-server-2008#p1
Bemalu Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mo 13.06.11 10:58 
Jackpot !

Danke,

mit dem neuen Verbindungsstring klappt es. Darf ich Dir trotzdem noch ein paar Fragen stellen:

  • Meinst Du mit "aushängen" die Verbindung trennen oder offline schalten ?

  • Wenn ich mit C# eine SQL-Server-Datenbankanwendung entwickeln will, brauche ich ja eine Tool um für Testzwecke (zum Beispiel um Abfragen vorgängig zu testen) auf die DB zuzugreifen. Ich dachte, "man" macht das mit Management Studio". Aber dann hätten ja viele andere das gleiche Problem gehabt wie ich. Bin ich nicht mehr auf dem Stand der Zeit ?

  • Zu SQL Server 2008 R2: Wenn eine Datenbank "gugus" heisst, lautet der Filename automatisch "gugus_Data.mdf" ich möchte aber dass die Datei "gugus.mdf" heisst. Wie kann ich das ändern ?

  • Stellt man in einer Applikation für jeden Datenbankzugriff neu eine Verbindung her, oder verbindet man beim Starten der Applikation und lässt die Verbindung bis zum Schliessen bestehen ?


Vielen Dank !

Bema


Zuletzt bearbeitet von Bemalu am Fr 24.06.11 10:31, insgesamt 1-mal bearbeitet
stendate
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19
Erhaltene Danke: 1



BeitragVerfasst: Fr 17.06.11 21:17 
user profile iconBemalu hat folgendes geschrieben Zum zitierten Posting springen:

Meinst Du mit "aushängen" die Verbindung trennen oder offline schalten ?


Nee, Rechtsklick >> Trennen

Zitat:

Wenn ich mit C# eine SQL-Server-Datenbankanwendung entwickeln will, brauche ich ja eine Tool um für Testzwecke (zum Beispiel um Abfragen vorgängig zu testen) auf die DB zuzugreifen. Ich dachte, "man" macht das mit Management Studio". Aber dann hätten ja viele andere das gleiche Problem gehabt wie ich. Bin ich nicht mehr auf dem Stand der Zeit ?


Doch, das ist schon genau richtig. Du hast eben versucht einzuhängen obwohl die Datenbank bereits eingehangen war, daher war auch das Transaktionsprotokoll bereits gelockt (das stand so ähnlich auch in der Fehlermeldungs-PDF die du gepostet hast).

Zitat:

Zu SQL Server 2008 R2: Wenn eine Datenbank "gugus" heisst, lautet der Filename automatisch "gugus_Data.mdf" ich möchte aber dass die Datei "gugus.mdf" heisst. Wie kann ich das ändern ?


Klar, im Management-Studio per Rechtsklick.

Zitat:

Stellt man in einer Applikation für jeden Datenbankzugriff neu eine Verbindung her, oder verbindet man beim Starten der Applikation und lässt die Verbindung bis zum Schliessen bestehen ?


Das kommt auf das zu erwartende Lastmuster an. MS SQL-Server und .NET ist aber schon darauf ausgelegt dass man Problemlos schnell neue Connections aufmachen und wieder schließen kann. Google einfach nach "Connection-Pooling".

Gruß S. (nicht M.) ;)
Trashkid2000
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 561
Erhaltene Danke: 137



BeitragVerfasst: Fr 17.06.11 22:03 
Ja, das Danke galt wohl eindeutig user profile iconstendate. Muss ich mal klarstellen.
Ich kann und will mich nicht mit femden Federn schmücken.
Wenn Du mal Zeit hat, kannst Du ja freundlicherweise Dein Post ändern.

Persönlich finde ich diese Attach-Database-Technologie (die es ja beim "richtigen" Server nicht gibt, sondern nur bei der Express-Variante) ziemlich schlecht. Ist aber meine persönliche Meinung. Und wie man sieht, führt es nur zu Problemen.
LG
stendate
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19
Erhaltene Danke: 1



BeitragVerfasst: Fr 17.06.11 22:15 
Servus Trashkid2000,

user profile iconTrashkid2000 hat folgendes geschrieben Zum zitierten Posting springen:

Persönlich finde ich diese Attach-Database-Technologie (die es ja beim "richtigen" Server nicht gibt, sondern nur bei der Express-Variante) ziemlich schlecht. Ist aber meine persönliche Meinung. Und wie man sieht, führt es nur zu Problemen.


ACK, die Vorteile sind IMHO im Embedded-Bereich zu finden, im Normalfall braucht das aber Niemand.
Leider ist es im Visual-Studio der Standard wenn man per "Design-First-Ansatz" an eine neue Datenbank herangeht.

PS: Ist "AttachDbFilename" bei der Vollversion echt nicht supportet? Sollte doch funktionieren wenn man auf LOCALHOST bleibt und die Berechtigung besitzt...