none
SQL Abfrage liefert im Management Studio richtiges Ergebnis, in C# nicht RRS feed

  • Frage

  • Hallo,

    ich hab mal wieder ein Problem.

    Ich überprüfe mittels SQL-Statement ob eine Datenbank existiert oder nicht. Wenn nein soll mir eine 0 ausgegeben werden, wenn ja eine 1.

    Auf Grundlage dieses Rückgabewertes wird nachher entschieden was beim Programmstart geschehen soll.

     

    Jetzt liefert mir das Statement zur Laufzeit des Programms allerdings den Fehlerzurück, dass die gesuchte Datenbank nicht gefunden werden konnte und somit bricht mir das Programm ab.

    "cannot open database requested by the login. The login failed."

    Wenn ich genau diese Query im Management Studio eintrage, dann erhalte ich meine 0 - so wie ich es möchte.

     

    Hier mal das Statement:

     

    SELECT CASE WHEN EXISTS (SELECT * FROM master.sys.databases WHERE name='Vereinsverwaltung') THEN 1 ELSE 0 AS Ergebnis
    

    Ich weiß nicht warum C# die Anfrage anders behandelt weil es gestern noch ohne weiteres funtkioniert hat - allerdings hab ich bis dahin die DB nicht getrennt. Das ist allerdings der Sinn der Sache. Die Verbindung soll überprüft werden und wenn im nachhinein eine 0 geliefert wird und eine weitere Prüfung ergibt dass die DB existiert aber nicht eingebunden ist, soll diese entsprechend mit einem SQL Scribt eingebunden werden.

    Wenn Sie nicht existiert wird sie heruntergeladen als "Rohling".

     

    Mein Source zum kompletten Aufruf sieht so aus:

     

     public static string chkDB()
        {
          try
          {
            string connString = Properties.Settings.Default.strConnectionString;
            SqlConnection conn = new SqlConnection(connString);
            string strSQL = "SELECT CASE WHEN EXISTS (SELECT * FROM master.sys.databases WHERE name='Vereinsverwaltung') THEN 1 ELSE 0 AS Ergebnis";
            SqlCommand cmd = new SqlCommand(strSQL, conn);
            conn.Open();
            SqlDataReader dr = cmd.ExecuteReader();
            while (dr.Read())
            {
              string count;
              count = (dr[0].ToString());
    
    
              //iCount = Convert.ToString(iCount);
              return count;
            }
            conn.Close();
           
          }
           catch(SqlException ex)
             {
               throw ex;
             }
          return chkDB();
        }
    

    Wäre mal wieder für jede Hilfe dankbar.

    Grüße

    Dom


    C# und VB.NET sind wie eine Schachtel Pralinen, ich weiß nie was ich bekomme xD
    Mittwoch, 18. Mai 2011 16:47

Antworten

  • Hallo Dom,

    Wenn ich Dich richtig verstehe, möchtest Du in etwa das erreichen, was der folgende Code zeigt.
    Stimmt's?

    using System;
    using System.Collections.Specialized;
    using Microsoft.SqlServer.Management.Smo;
    
    namespace Console1
    {
     class Program {
      private const string DATABASENAME = "Vereinsverwaltung";
      private const string INSTANCENAME = @".\SQLEXPRESS";
      
      static void Main(string[] args) {
       Server server = new Server(INSTANCENAME);
    
       if (server.Databases.Contains(DATABASENAME)) {
        // Evtl. überprüfen ob auch die richtige DB-Datei angefügt ist
        // z.B. server.Databases[DATABASENAME].FileGroups[0].Files[0].FileName;
       } else { 
        // Datenbank ist nicht angefügt, also anfügen
        string mdfPath = GetMdfPathFromConfiguration();
        server.AttachDatabase(DATABASENAME, new StringCollection() { mdfPath });
       }
      }
    
      private static string GetMdfPathFromConfiguration() {
       return @"C:\Programme\Microsoft SQL Server\MSSQL.1\MSSQL\Data\Vereinsverwaltung.mdf"; // mockup
      }
     }
    }
    

    Gruß
    Marcel


    Mittwoch, 18. Mai 2011 19:14
    Moderator

Alle Antworten

  • Poste mal deinen ConnectionString...

    Evtl. haben sich die Anmeldedaten geändert?!
    Mittwoch, 18. Mai 2011 16:57
  • Hi,

    so wirklich hab ichs nicht verstanden.

    Im Management Studio bist Du als welcher Benutzer angemeldet? Wenn es ein anderer Account als der, der im ConnectionString angegeben ist: Welche Berechtigungen hat der Benutzer, den Du fürs SSMS verwendest und welche hat der, der im ConnectionString angegeben ist?

    Für mich hört sich das eher nach einem fehlgeschlagenen Login als nach einer "nicht vorhandenen Datenbank" an.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Mittwoch, 18. Mai 2011 16:58
    Moderator
  • Hi.

     

    das ist der ConnectionString: Data Source=.\SQLEXPRESS;Initial Catalog=Vereinsverwaltung; Integrated Security = TRUE;

     

    Ich melde mich auch mit meinem Windows Account beim SSMS an. Die Datenbank an sich ist definitiv getrennt.
    Der Benutzer hat als StandardDB die Master zugewiesen bekommen.

    Als Berechtigungen sind mir public und sysadmin gesetzt.

     

    Der CS ist bei den Settings hinterlegt und haben sich seit dem Test bei "eingebundener " DB nicht geändert. Mich wurmt das weil es schon seltsam ist. Er steigt mir direkt nach dem "Con.Open()" aus.

     

    Grüße,

    Dom


    C# und VB.NET sind wie eine Schachtel Pralinen, ich weiß nie was ich bekomme xD
    Mittwoch, 18. Mai 2011 17:03
  • Der Benutzer muss auch eine Zuordnung zu der DB haben.

    Warum ist die Datenbank denn getrennt?
    Mittwoch, 18. Mai 2011 17:20
  • Es geht um folgendes Szenario:

     

    Benutzer installiert Anwendung inkl. SQL Server 2008 Express. Die DB ist noch nicht eingebunden, existiert aber bereits und wird beim ersten Programmstart in das DATA Verzeichnis kopiert.

    Dann wird geprüft und wenn sie noch nicht eingebunden ist (zu Fuß s.u) wird sie durch ein SQL Script eingebunden.

    Sollte der Benutzer die Datenbank vor dem ersten Start "zu Fuß" einbinden, dann brauch ich eine Überprüfung. Es kann ja auch mal sein, das hatte ich auch schon, dass das SSMS die Verbindung zur DB verliert. Dann ist diese Funktion durchaus brauchbar.

     

    Da es sich hierbei um eine Template DB handelt und ich sie nicht zur Laufzeit erstellen wollte, hatte ich mir diesen Weg überlegt.

    Wie kann ich dem SQL Server denn Verständlich machen, dass der User auf die nicht vorhandene DB zugreifen darf? Wüsste nicht wie ich das festlegen können sollte, denn immerhin kenn ich die Anmeldedaten der Personen nicht die die Software später einsetzen.

     

     


    C# und VB.NET sind wie eine Schachtel Pralinen, ich weiß nie was ich bekomme xD
    Mittwoch, 18. Mai 2011 17:25
  • Hi,

    Ich melde mich auch mit meinem Windows Account beim SSMS an. Die Datenbank an sich ist definitiv getrennt.
    Der Benutzer hat als StandardDB die Master zugewiesen bekommen.

    es wird aber nicht die Standarddatenbank verwendet, sondern die "Vereinsverwaltung", die es ja nun nicht gibt. Ändere das mal. Also den Datenbanknamen rausnehmen, dann sollte das ggfs. auch funktionieren (wenn es nicht noch an anderen [Berechtigungs]problemen liegt).

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Mittwoch, 18. Mai 2011 17:25
    Moderator
  • Die Standarddatenbank kann ich ja nicht rausnehmen, die ist halt master..... und bei Benutzerzuordnungen ist nichts mehr drin.

     

    Gibt es denn sonst noch eine Möglichkeit zu Prüfen ob die DB da ist? Ich mein, jede SELECT Abfrage wird mir ne Exception bringen wenn sie sich nicht verbinden kann. Und im Catch zu sagen dass er den Schritt mit dem Einbinden erledigen soll ist auch mumpitz. Es sei denn ich frage zusätzlich noch ab ob die Datenbank im DATA Verzeichnis hinterlegt ist.

    Könnte ich es auf Unsaubere Art auch so regeln:

    - Prüfen ob DB vorhanden

       - wenn Exception dann prüfen ob Datei im Verzeichnis DATA liegt,

           - wenn nein, dann kopieren und einbinden

           - wenn ja, dann einbinden

     

    Das wäre das einzige was mir einfallen würde denn die von allem ist frisch auf dem System. Auf dem wo es vorher lief und ich noch keine Grundsätzlichen Änderungen an der Datenbank oder Berechtigungen etc. vornahm, läuft es auch nicht. Das ist ziemlicher Murks.

     


    C# und VB.NET sind wie eine Schachtel Pralinen, ich weiß nie was ich bekomme xD
    Mittwoch, 18. Mai 2011 17:36
  • Hi,
    das ist der ConnectionString: Data Source=.\SQLEXPRESS;Initial Catalog=Vereinsverwaltung; Integrated Security = TRUE;
    das war/ist dein ConnectionString.

    Die Standarddatenbank kann ich ja nicht rausnehmen, die ist halt master.....

    Du gibst im ConnectionString die Datenbank "Vereinsverwaltung" an. Wie soll sich die SqlConnection dann ordentlich aufbauen, wenn es diese Datenbank gar nicht gibt.

    Gibt es denn sonst noch eine Möglichkeit zu Prüfen ob die DB da ist? Ich mein, jede SELECT Abfrage wird mir ne Exception bringen wenn sie sich nicht verbinden kann. Und im Catch zu sagen dass er den Schritt mit dem Einbinden erledigen soll ist auch mumpitz. Es sei denn ich frage zusätzlich noch ab ob die Datenbank im DATA Verzeichnis hinterlegt ist.

    Ich persönlich denke, dass das, was Du da machst, so oder so Mumpitz ist.

    Klappen wird es aber, wenn Du im ConnectionString eben keine nicht vorhandene Datenbank angibst. Entweder weg lassen oder explizit master angeben. Wenn der sich verbindende Account SA Rechte hat, kann er die DB dann auch anhängen oder neu erstellen.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Mittwoch, 18. Mai 2011 18:30
    Moderator
  • Hi,

     

    knallhart aber gut - danke :)

     

    Wenn ich dich richtig verstehe sollte ich also im connString eher die DB Weglassen oder den Master angeben und mich dann wenn diese existiert auf die entsprechende VV beziehen?

     

    Das leuchtet mir ein. Andernfalls muss ich es wirklich mit dem erstellen machen.Gibt´s denn irgendwelche Regeln zum erstellen von Connectionstrings bzw. irgendwelche Richtlinien? Das wäre natürlich himmlisch, dann bräuchte ich euch auch nicht mehr so sehr zu nerven.

    Mit dem Testen ob die Datenbank da oder hier existiert also das File klappt nur bedingt. Also kann ich den Gedanken direkt verwerfen.

    Dann wäre noch die Frage, wie erteile ich dem User SA rechte ohne dass ich einfluss nehme, eben gar nicht. Die, die die Software mal nutzen als Betatester quasi haben absolut noch viel weniger ahnung als ich im SQL-Bereich und das ist schon unter 0.....

    Ich hoffe ich hab dich bis hier hin soweit richtig verstanden Stefan.

    (Ich war im übrigen ein Narr als ich damals mit VB anfing und mich auf die scheuslichen Assistenten verlassen habe).....



    C# und VB.NET sind wie eine Schachtel Pralinen, ich weiß nie was ich bekomme xD
    Mittwoch, 18. Mai 2011 18:43
  • Hallo Dom,

    Wenn ich Dich richtig verstehe, möchtest Du in etwa das erreichen, was der folgende Code zeigt.
    Stimmt's?

    using System;
    using System.Collections.Specialized;
    using Microsoft.SqlServer.Management.Smo;
    
    namespace Console1
    {
     class Program {
      private const string DATABASENAME = "Vereinsverwaltung";
      private const string INSTANCENAME = @".\SQLEXPRESS";
      
      static void Main(string[] args) {
       Server server = new Server(INSTANCENAME);
    
       if (server.Databases.Contains(DATABASENAME)) {
        // Evtl. überprüfen ob auch die richtige DB-Datei angefügt ist
        // z.B. server.Databases[DATABASENAME].FileGroups[0].Files[0].FileName;
       } else { 
        // Datenbank ist nicht angefügt, also anfügen
        string mdfPath = GetMdfPathFromConfiguration();
        server.AttachDatabase(DATABASENAME, new StringCollection() { mdfPath });
       }
      }
    
      private static string GetMdfPathFromConfiguration() {
       return @"C:\Programme\Microsoft SQL Server\MSSQL.1\MSSQL\Data\Vereinsverwaltung.mdf"; // mockup
      }
     }
    }
    

    Gruß
    Marcel


    Mittwoch, 18. Mai 2011 19:14
    Moderator
  • Hi Marcel,

     

    das sieht schonmal gut aus - ich werde es nachher wenn ich nochmal ruhe habe ausprobieren. Schaut aber fast so aus als sollte das klappen.....

     

    Wenn ja, und würde es hier ein "Helfer des Tages" Button geben, dann würdest du ihn von mir bekommen xD

     

    Grüße,

     

    Dom


    C# und VB.NET sind wie eine Schachtel Pralinen, ich weiß nie was ich bekomme xD
    Mittwoch, 18. Mai 2011 19:33
  • Hi,

    Wenn ja, und würde es hier ein "Helfer des Tages" Button geben, dann würdest du ihn von mir bekommen xD

    Ich denke "Als Antwort markieren" würde schon mal einen guten Anfang machen :)

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Mittwoch, 18. Mai 2011 20:03
    Moderator