Avatar billede Slettet bruger
02. februar 2008 - 08:25 Der er 40 kommentarer og
1 løsning

Detach en database

Jeg har et program, som kræver, at man kan eksportere en database. Men når jeg kopiere databasen, gennem kode, skriver den at den ikke kan få adgang til databasen, da den bruges af en anden proces. Jeg har læst at man skal detach databasen, men hvordan gør jeg det? Og i så fald, hvordan attack'er jeg den igen?

Tak
Avatar billede lordnelson Seniormester
02. februar 2008 - 09:04 #1
Er det en MSSQL
Avatar billede Slettet bruger
02. februar 2008 - 09:26 #2
Ja, jeg har lavet en .mdf database i visual c#.
Avatar billede nielle Nybegynder
02. februar 2008 - 09:34 #3
Noget i denne stil?

using System;
using System.Collections.Specialized;

// Opret desuden references til:
// 1) Microsoft.SqlServer.ConnetionInfo.dll
// 2) Microsoft.SqlServer.Smo.dll
// using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;  // Server Management Objects

namespace e817653
{
    class Program
    {
        static void Main(string[] args)
        {
            Server server = new Server();

            Console.WriteLine("Før deattach:");
            foreach (Database database in server.Databases)
                Console.WriteLine("\t" + database.Name);


            // Deattach database.

            server.DetachDatabase("dinDatabase", true);

            Console.WriteLine("Efter deattach:");
            foreach (Database database in server.Databases)
                Console.WriteLine("\t" + database.Name);


            // Attach database.

            string datFile = @"C:\Programmer\Microsoft SQL Server\MSSQL.2\MSSQL\Data\dinDatabase.mdf";
            string logFile = @"C:\Programmer\Microsoft SQL Server\MSSQL.2\MSSQL\Data\dinDatabase_log.ldf";

            StringCollection files = new StringCollection();
            files.Add(datFile);
            files.Add(logFile);

            server.AttachDatabase("dinDatabase", files);


            Console.WriteLine("Efter deattach:");
            foreach (Database database in server.Databases)
                Console.WriteLine("\t" + database.Name);

            server.ConnectionContext.Disconnect();
        }
    }
}
Avatar billede Slettet bruger
02. februar 2008 - 09:52 #4
Det virker desværre ikke. Den skriver stadig at den bruges af en anden proces. Her er min kode:

Server server = new Server();

Console.WriteLine("Før deattach:");
foreach (Database database in server.Databases)
Console.WriteLine("\t" + database.Name);


// Deattach database.

server.DetachDatabase("MinDatabase", true);

Console.WriteLine("Efter deattach:");
foreach (Database database in server.Databases)
Console.WriteLine("\t" + database.Name);





string Location = openFileDialog1.FileName;
string NewLocation = @"MinDatabase.mdf";

using (FileStream fs = File.Create(Location)) { }

// Sletter den eksisterende fil hvis den er findes
File.Delete(NewLocation);

// Kopiere filen
File.Copy(Location, NewLocation);
Avatar billede nielle Nybegynder
02. februar 2008 - 10:00 #5
Hvor står der at den bruges af en anden process?

Bliver der smidt en exception når du køre din kode - i hvilken linje?
Avatar billede nielle Nybegynder
02. februar 2008 - 10:02 #6
(... og hvorfor har du forresten ikke fjernet mine Console-linjer siden du jo køre i et Windows program i stedet for en consol?)
Avatar billede Slettet bruger
02. februar 2008 - 10:18 #7
Jeg har rodet lidt med koden du skrev og kommet frem til følgende. Nu får jeg en anden fejl:

private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            try
            {
                string Location = @"MinDatabase.mdf
                string NewLocation = saveFileDialog1.FileName;

                Server server = new Server();


                // Deattach database.

                server.DetachDatabase("MinDatabase", true); // Her får jeg fejlen. Den skriver "Detach failed for Server 'ServerNavn'.


                // Sletter den eksisterende fil hvis den findes
                File.Delete(NewLocation);

                // Kopiere filen
                File.Copy(Location, NewLocation);

             
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
Avatar billede nielle Nybegynder
02. februar 2008 - 10:31 #8
Måske er databasen allerede detachet efter et af de tidligere forsøg...
Avatar billede Slettet bruger
02. februar 2008 - 10:33 #9
Nej. Hvis jeg fjerner den del der skal detache databasen, skriver den at databasen bliver brugt af en anden process.
Avatar billede nielle Nybegynder
02. februar 2008 - 10:37 #10
Hvis databasen allerede er detachet, vil du få en fejl som den du beskriver.

At filen bruges af en anden process er ikke nødvendigvis det samme som at sie at den er attachet. Det kan sagtens være noget helt andet som har låst filerne.
Avatar billede nielle Nybegynder
02. februar 2008 - 10:40 #11
Hvsi du har SQL Server Management Studio kan du gå ind og kigge efter om dasen er attachet eller ef.

Alternativt kan du kigge efter om den bliver listet med:

foreach (Database database in server.Databases)
                Console.WriteLine("\t" + database.Name);

Hvis den ikke optræder der, så er den ikke attachet.
Avatar billede Slettet bruger
02. februar 2008 - 10:40 #12
Okay. Har du en idé om hvordan man undgår det? Jeg kan flytte koden op i main-metoden lige inden 'initializecomponent', uden det skaber problemer...
Avatar billede nielle Nybegynder
02. februar 2008 - 10:43 #13
Hvad mener du med at det "ikke skaber problemer" - virker koden så lige pludselig, eller hvad?
Avatar billede Slettet bruger
02. februar 2008 - 10:48 #14
Ja, hvis jeg flytter den del der kopiere op over initializecomponent, bliver databasen kopieret som den skal. Jeg har prøvet med den metode du skrev, men der skriver den 'Failed to connect to server ..':

foreach (Database database in server.Databases)
                Console.WriteLine("\t" + database.Name);
Avatar billede nielle Nybegynder
02. februar 2008 - 10:59 #15
Tja, så er det jo tydeligvis et eller andet i dit eget program som låser database-filen. ...og ikke at den stadigvæk skulle være attachet.
Avatar billede Slettet bruger
02. februar 2008 - 11:04 #16
Okay... Jeg vil prøve at rode lidt med det.
Avatar billede nielle Nybegynder
02. februar 2008 - 11:06 #17
Denne kode virker i hvert fald hos mig:

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            try
            {
                string datFile = @"C:\Programmer\Microsoft SQL Server\MSSQL.2\MSSQL\Data\dinDatabase.mdf";
                string logFile = @"C:\Programmer\Microsoft SQL Server\MSSQL.2\MSSQL\Data\dinDatabase_log.ldf";

                string newLocation = saveFileDialog1.FileName;

                Server server = new Server();

                // Deattach database.
                server.DetachDatabase("dinDatabase", true);

                // Sletter den eksisterende fil hvis den findes
                if (File.Exists(newLocation))
                    File.Delete(newLocation);

                // Kopiere filen
                File.Copy(datFile, newLocation);

                // Attach database.
                StringCollection files = new StringCollection();
                files.Add(datFile);
                files.Add(logFile);

                server.AttachDatabase("dinDatabase", files);

            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
Avatar billede Slettet bruger
02. februar 2008 - 11:23 #18
Den skriver stadig Detach failed for server... Men hvis jeg åbner for den mappe du har skrevet i koden, ligger min database heller ikke der i.
Avatar billede Slettet bruger
02. februar 2008 - 11:25 #19
Jeg får fejlen her:
// Deattach database.
server.DetachDatabase("dinDatabase", true);
Avatar billede nielle Nybegynder
02. februar 2008 - 11:29 #20
Du bliver selvfølgeli nødt til at finde ud af hvor filen ligger hos dig.

Dette har dog ingen indflydelse på om databasen kan detaches, men *kun* på om den kan gen-attaches.

Uden at databasen gen-attaches, vil du som sagt få den fejl du fortæller om der.
Avatar billede Slettet bruger
02. februar 2008 - 11:57 #21
Jeg har fundet databasen, men jeg tror det er 'Server' det er galt med. Uanset hvad jeg gør som bruger server melder den fejl. F.eks. når jeg skriver server.KillAllProcesses("MinDatabase")
Avatar billede nielle Nybegynder
02. februar 2008 - 16:07 #22
Hvilken fejl?
Avatar billede Slettet bruger
02. februar 2008 - 16:29 #23
Så får jeg 'KillAllProcess failed for server...'
Avatar billede nielle Nybegynder
02. februar 2008 - 16:34 #24
Mystisk.

Men hvorfor prøver du i øvrigt at gøre det? Databasen kan sagtens detaches uden at det skulel være nødvendigt.
Avatar billede Slettet bruger
02. februar 2008 - 16:59 #25
Jeg gjorde det kun for at prøve. Kan det være noget med at jeg kører Vista? Der er nogle mapper jeg ikke har adgang til hvis ikke jeg er administrator. Det er dog stadig SQL Server 2005.
Avatar billede nielle Nybegynder
02. februar 2008 - 18:14 #26
Hvordan ser din kode ud lige nu?

Server må vel virke korrekt siden at du allerede har set det virke en gang tidligere (02/02-2008 10:48:12).
Avatar billede Slettet bruger
02. februar 2008 - 19:29 #27
Ja det har du ret i. Her er koden:


try
            {
                string datFile = @"Database.mdf";
                string logFile = @"Database_log.ldf";

                string newLocation = saveFileDialog1.FileName;
                Server server = new Server();

                // Deattach database.
                server.DetachDatabase("DatabaseNavn", true); // Her kommer fejlen

                // Sletter den eksisterende fil hvis den findes
                if (File.Exists(newLocation))
                    File.Delete(newLocation);

                // Kopiere filen
                File.Copy(datFile, newLocation);

                             
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
Avatar billede nielle Nybegynder
02. februar 2008 - 20:44 #28
1) Hvordan ved du at databasen overhovedet er attachet? Hvis den er blevet deattachet ved en tidligere kørsel, vil det fejle hvis man forsøger at deattache den.

2) Du har ikke noget kode somattacher databasen igen efter at den er blevet kopieret. Derfor vil databasen fortsat være detattachet nuste gang koden køres - hvilket giver en fejl i følge 1)

3) Dine filnavne *skal* bruge absolutte stier. Du kan ikke bruge File.Copy() ellers. Hvis du alligevel forsøger, vil koden fejle (og så vil databasen ikke blive attachet igen ... hvsi du ellers havde den kode med.
Avatar billede Slettet bruger
02. februar 2008 - 23:37 #29
1) Jeg har en attach kode under detach koden.
2) Jeg har aldrig oplevet at den gik videre uden at melde fejl.
3) Når jeg sætter koden op i over initializecomponent, kopiere den databasen som den skal selvom jeg ikke har den absolutte sti.
Avatar billede nielle Nybegynder
03. februar 2008 - 07:35 #30
1) Det er altså lidt svært at hjælpe uden al den relevante kode...

2) Hvis du tilfældigvis aldrig har kørt koden på et tidspunkt hvor databasen faktisk var attachet på kørselstidspunktet, er det vel at forvente.

Jeg har ingen anelse om hvorvidt at det faktisk er tilfældet, men hvis den stump kode altid fejler så er din database detachet det meste af tiden.

I øvrigt virker koden. Du har bare aldrig fået den til at virke lige der på det sted i programmet ... og det er vel *det* som er det mystiske.

3) Det skyldes nok at du får oprettet databasen på samme sted hvor dit program køre fra. Hvis du opretter den fra dit program, er dette vel egentlig ikke så underligt. Den sti som jeg brugte i 02/02-2008 11:06:41 er den sti som SQL Server selv foreslår hvis man opretter databasen derfra.
Avatar billede nielle Nybegynder
03. februar 2008 - 08:39 #31
Denne kode burde være mere robust for om databasen er attachet eller ej fra starten af.

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            Server server = new Server();

            string datFile = @"C:\Programmer\Microsoft SQL Server\MSSQL.2\MSSQL\Data\dinDatabase.mdf";
            string logFile = @"C:\Programmer\Microsoft SQL Server\MSSQL.2\MSSQL\Data\dinDatabase_log.ldf";


            // Deattach databasen. //
            try
            {
                server.DetachDatabase("dinDatabase", true);
            }
            catch (FailedOperationException ex)
            {
                if (ex.InnerException is MissingObjectException)
                {
                    MessageBox.Show("Databasen var åbenbart ikke attachet.\nVi prøver alligevel at gå vidre.",
                        "Hmmm",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                }
                else
                    throw;  // Ukendt fejl. Throw den igen.
            }


            // Kopier database filen/filerne. //
            try
            {
                string newLocation = saveFileDialog1.FileName;

                // Sletter den eksisterende fil hvis den findes
                if (File.Exists(newLocation))
                    File.Delete(newLocation);

                // Kopiere filen
                File.Copy(datFile, newLocation);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Problem med at copiere databasefilen\n" + ex.Message);
            }
            finally
            {
                // Attach databasen igen. //

                StringCollection files = new StringCollection();
                files.Add(datFile);
                files.Add(logFile);

                server.AttachDatabase("dinDatabase", files);
            }
        }
Avatar billede Slettet bruger
03. februar 2008 - 10:43 #32
Nu kører den bare i ring, og starter forfra efter 'throw: //Ukendt fejl. Throw den igen.'
Avatar billede nielle Nybegynder
03. februar 2008 - 11:20 #33
Hvordan "køre i ring"? Der er ikke nogen loop i den kode jeg har skrevet.
Avatar billede Slettet bruger
03. februar 2008 - 11:29 #34
Efter throw starter den forfra, og kører ned til throw igen, hvorfra den starter forfra igen osv.
Avatar billede nielle Nybegynder
03. februar 2008 - 11:51 #35
Hvordan ser din kode ud?

Det er ikke throw selv som får det til at løbe i ring.
Avatar billede Slettet bruger
03. februar 2008 - 12:18 #36
Når den kommer til throw stopper den, og hvis jeg så trykker på OK knapper på savefiledialog1 igen, begynder den selvfølgelig forfra.
Avatar billede nielle Nybegynder
03. februar 2008 - 12:34 #37
Tak. Du må meget gerne gøre mere ud af at beskrive hvad du gør og hvad der så sker (og hvad du forventede). Desværre sidder jeg ikke ved din skærm og min ESP har aldrig været noget særligt. Og så er der jo kun gætteri tilbage...

Hvad får du hvis du erstatter den throw med dette:

            // Deattach databasen. //
            try
            {
                server.DetachDatabase("dinDatabase", true);
            }
            catch (FailedOperationException ex)
            {
                if (ex.InnerException is MissingObjectException)
                {
                    MessageBox.Show("Databasen var åbenbart ikke attachet.\nVi prøver alligevel at gå vidre.",
                        "Hmmm",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show("InnerException: " +
                        ex.InnerException.GetType().ToString() +
                        "\n" +
                        ex.InnerException.Message);
                }
            }
Avatar billede Slettet bruger
03. februar 2008 - 12:46 #38
Så får jeg beskeden:
InnerException:
Microsoft.SqlServer.Management.Common.ConnectionFailureException
Failed to connect to server ..
Avatar billede nielle Nybegynder
03. februar 2008 - 12:56 #39
Har du nogen anelse om hvorfor programmet ikke kan forbinde til SQL serveren? Det kan den jo åbenbart hvis du har den et andet sted i koden?
Avatar billede Slettet bruger
03. februar 2008 - 13:13 #40
Nej. Men jeg tror jeg dropper at lave funktionen, og bruger en mysql database i stedet. Mange tak for hjælpen. Hvordan giver man point?
Avatar billede nielle Nybegynder
03. februar 2008 - 13:24 #41
MySQL er udemærket, men jeg er 100 % sikker på at det sagtent kan lade sig gøre at få det til at virke med SQL Server. Det er sikkert bare en dum lille ting som ligger og spænder ben.

Du kan først give point når der er nogen som har lagt et svar, så det gør jeg da lige.

Men ellers er jeg ad frisk til at fortsætte... :^)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester