Best practice to create (on demand) SQL Server 2008 Express databases in C#?

馋奶兔 提交于 2019-11-30 07:33:11

There's lots you can do with 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;
    }

}

An alternate solution is to use SQLite rather than SQL Express. You can even continue to use ADO.NET if you use this solution. SQLite databases are simply files, and your connection strings can refer to the file path. When a user wants to open their file, they can select an actual file.

I get the impression that this database will live locally on user's machine. If that's the case, sql server express is not usually a good database choice. It's a server-class engine rather than a desktop or in process engine. Instead, there are a number of good in process engines you can use: Sql Server Compact Edition, Sqlite (as mentioned by Jacob) or even Access.

If you believe SQL Server Express 2008 is the right choice (sqllite does seem to fit better though), I would look at using User Instances which will allow non-administrators to add databases from files as you describe.

This article shows how to create a new database, and attach it to a SQL Server database instance:

How to: Attach a Database File to SQL Server Express
http://msdn.microsoft.com/en-us/library/ms165673.aspx

These article shows how to manage the attaching and detaching of existing databases: 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

For the following connection string for SQL Server 2008 R2.

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

you can do

  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;
  }

Thanks to Mr. Harvey for pointing the right direction. Although in my case, I have to make these small changes. Because, I use the windows authentication.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!