2010-02-27 17 views
5

Lo scopo è gestire i dati dell'utente (è possibile chiamarli progetto, documento, file o qualsiasi altra cosa) in un nuovo database SQL Server 2008 Express. Si prevede che i dati occupino molto meno spazio rispetto ai 4 GB disponibili con l'Express Edition (che è anche gratuita da distribuire).Procedura consigliata per creare (su richiesta) database SQL Server 2008 Express in C#?

Ad esempio, ogni volta che l'utente seleziona File-> Nuovo comando, verrà creato un nuovo database vuoto nella posizione specificata. D'altra parte, un comando simile, File-> Apri deve fornire supporto per recuperare l'elenco dei database per selezionarne uno per l'apertura.

Quindi, le seguenti questioni devono essere risolte: a) La domanda deve essere in grado di creare la stringa di connessione e collegare il database di SQL Server 2008 Express tramite il codice (C#) b) La domanda deve essere in grado di recuperare (sempre attraverso il codice) un elenco con tutti i database disponibili, per dare all'utente la possibilità di selezionarne uno da aprire.

Penso che sarebbe utile avere un database modello in risorse e copiarlo nella posizione specificata dall'utente.

Pensi che sia una soluzione funzionante? Hai qualche suggerimento?

+0

Grazie a tutti per la risposta. È bello sapere che ci sono anche altre opzioni, ma ad essere onesti, apprezzerei alcune considerazioni specifiche su SQL Server 2008 Express. @Robert, penso che tu abbia ragione, e inoltre, il motivo per cui sto pensando di utilizzare questa soluzione, è principalmente dovuto alla scalabilità. Ad un certo punto in futuro userò la versione "completa" di SQL Server. @thekaido, le istanze utente sono ciò che avevo in mente al momento. Ciò che mi disturba è come posso codificare l'allegato, ad esempio, del database in SQL Server dall'applicazione Winforms. Qualche suggerimento? – ileon

risposta

16

C'è molto che potete fare con SQL Server Management Objects (SMO):

// Add a reference to Microsoft.SqlServer.Smo 
// Add a reference to Microsoft.SqlServer.ConnectionInfo 
// Add a reference to Microsoft.SqlServer.SqlEnum 

using Microsoft.SqlServer.Management.Smo; 
using System.Collections.Generic; 
using System.Collections.Specialized; 
using System.Data; 

public class SqlServerController 
{ 

    private Server m_server = null; 

    public SqlServerController(string server) 
    { 
     m_server = new Server(server); 
    } 

    public void AttachDatabase(string database, StringCollection files, 
     AttachOptions options) 
    { 
     m_server.AttachDatabase(database, files, options); 
    } 

    public void AddBackupDevice(string name) 
    { 
     BackupDevice device = new BackupDevice(m_server, name); 
     m_server.BackupDevices.Add(device); 
    } 

    public string GetServerVersion(string serverName) 
    { 
     return m_server.PingSqlServerVersion(serverName).ToString(); 
    } 

    public int CountActiveConnections(string database) 
    { 
     return m_server.GetActiveDBConnectionCount(database); 
    } 

    public void DeleteDatabase(string database) 
    { 
     m_server.KillDatabase(database); 
    } 

    public void DetachDatabase(string database, bool updateStatistics, 
     bool removeFullTextIndex) 
    { 
     m_server.DetachDatabase(database, updateStatistics, removeFullTextIndex); 
    } 

    public void CreateDatabase(string database) 
    { 
     Database db = new Database(m_server, database); 
     db.Create(); 
    } 

    public void CreateTable(string database, string table, 
     List<Column> columnList, List<Index> indexList) 
    { 
     Database db = m_server.Databases[database]; 
     Table newTable = new Table(db, table); 

     foreach (Column column in columnList) 
      newTable.Columns.Add(column); 

     if (indexList != null) 
     { 
      foreach (Index index in indexList) 
       newTable.Indexes.Add(index); 
     } 

     newTable.Create(); 

    } 

    public Column CreateColumn(string name, DataType type, string @default, 
     bool isIdentity, bool nullable) 
    { 
     Column column = new Column(); 

     column.DataType = type; 
     column.Default = @default; 
     column.Identity = isIdentity; 
     column.Nullable = nullable; 

     return column; 
    } 

    public Index CreateIndex(string name, bool isClustered, IndexKeyType type, 
     string[] columnNameList) 
    { 

     Index index = new Index(); 

     index.Name = name; 
     index.IndexKeyType = type; 
     index.IsClustered = isClustered; 

     foreach (string columnName in columnNameList) 
      index.IndexedColumns.Add(new IndexedColumn(index, columnName)); 

     return index; 
    } 

} 
+1

Wow, questo ha appena reso la mia giornata. Tutti gli altri stanno cercando di dissuadere il richiedente dal tentare questa soluzione, e tu sei semplicemente arrivato e rispondere con un breve, pulito, conciso elenco dei codici. Congratulazioni, buon signore, hai vinto il mio upvote. –

1

Una soluzione alternativa è utilizzare SQLite anziché SQL Express. Puoi anche continuare a utilizzare ADO.NET se utilizzi this solution. I database SQLite sono semplicemente file e le stringhe di connessione possono fare riferimento al percorso del file. Quando un utente vuole aprire il suo file, può selezionare un file reale.

1

Ho l'impressione che questo database vivrà localmente sul computer dell'utente. In questo caso, SQL Server Express non è in genere una buona scelta di database. È un motore di classe server piuttosto che un desktop o un motore di elaborazione. Invece, ci sono un certo numero di buoni motori di processo che puoi usare: Sql Server Compact Edition, Sqlite (come detto da Jacob) o anche Access.

+1

Un database di SQL Server è costituito da due file (.MDF e .LDF). Se è possibile gestire in modo elegante il collegamento e il distacco dei database, non vedo alcun motivo per cui SQL Server Express non possa essere utilizzato. http://msdn.microsoft.com/en-us/library/ms190794.aspx –

+0

@Robert: un database SQL Server è anche il motore che viene eseguito come servizio sulla macchina. –

+0

Fintanto che si evita l'accesso, si è in testa al gioco. –

1

Se si ritiene che SQL Server Express 2008 sia la scelta giusta (sqllite sembra adattarsi meglio però), vorrei considerare l'utilizzo di User Instances che consentirà ai non amministratori di aggiungere database dai file come descritto.

1

In questo articolo viene illustrato come creare un nuovo database, e collegarlo ad un'istanza del database di SQL Server:

Procedura: Allega un file di database a SQL Server Express
http://msdn.microsoft.com/en-us/library/ms165673.aspx

Questi articolo mostra come gestire l'attaccare e staccare di database esistenti: http://msdn.microsoft.com/en-us/library/ms190794.aspx

http://www.databasejournal.com/features/mssql/article.php/2224361/Attaching-and-Detaching-Databases-on-SQL-Server.htm

+1

Puoi darmi un suggerimento su come questo può essere implementato nel codice C# da un modulo di Windows (ad esempio, utilizzando ADO.NET)? Grazie. – ileon

+1

È necessario eseguire le stored procedure per creare, allegare e scollegare i database. Per fare ciò in C#, aprire un oggetto SqlConnection con una stringa di connessione appropriata, creare un oggetto SqlCommand che passa l'oggetto SqlConnection e il nome della stored procedure che collega o scollega il database, aggiungere alcuni oggetti parametro all'oggetto SqlCommand e eseguire lo SqlCommand utilizzando ExecuteNonQuery(). Un esempio completo è qui, a metà pagina: http://www.c-sharpcorner.com/UploadFile/dclark/InsOutsinCS11302005072332AM/InsOutsinCS.aspx –

+0

Grazie Robert. Sei stato molto utile. – ileon

0

Per la seguente stringa di connessione per SQL Server 2008 R2.

<connectionstring>Data Source=.\SQLEXPRESS;Initial Catalog=MyDatabase;Integrated Security=True;Pooling=True</connectionstring> 

si può fare

var connectionString = new SqlConnectionStringBuilder(connectionString); 

    var serverConnection = new ServerConnection("DatabaseInstanceName in server"); 

    var serverInstance = new Server(serverConnection); 

    if (serverInstance.Databases.Contains(connectionString.InitialCatalog)) 
     serverInstance.KillDatabase(connectionString.InitialCatalog); 

    var db = new Database(serverInstance, connectionString.InitialCatalog); 

    try 
    { 
    db.Create(); 
    } 
    catch (SqlException ex) 
    { 
    throw; 
    } 

Grazie a Mr. Harvey per indicare la giusta direzione. Anche se nel mio caso, devo fare questi piccoli cambiamenti.Perché, io uso l'autenticazione di Windows.

Problemi correlati