在 C# 中创建(按需)SQL Server 2008 Express 数据库的最佳实践?

Posted

技术标签:

【中文标题】在 C# 中创建(按需)SQL Server 2008 Express 数据库的最佳实践?【英文标题】:Best practice to create (on demand) SQL Server 2008 Express databases in C#? 【发布时间】:2011-01-21 20:58:07 【问题描述】:

目的是在全新的 SQL Server 2008 Express 数据库中处理用户的数据(您可以称它们为项目、文档、文件或其他任何内容)。预计数据占用的空间比 Express 版本(也可免费分发)提供的 4GB 空间小得多。

例如,每次用户选择 File->New 命令时,都会在指定位置创建一个新的空数据库。另一方面,类似的命令 File->Open 必须支持检索数据库列表以选择打开一个。

因此,必须解决以下问题: a) 应用程序必须能够创建连接字符串并通过代码 (C#) 将数据库附加到 SQL Server 2008 Express b) 应用程序必须能够(再次通过代码)检索包含所有可用数据库的列表,以便用户有机会选择打开一个。

我认为在资源中有一个模板数据库并将其复制到用户指定的位置会很有帮助。

您认为这是一个可行的解决方案吗?你有什么建议吗?

【问题讨论】:

谢谢大家的回复。很高兴知道还有其他选项,但老实说,我希望能有一些关于 SQL Server 2008 Express 的特别想法。 @Robert,我认为您是对的,此外,我考虑使用此解决方案的原因主要是由于可扩展性。在将来的某个时候,我将使用“完整”的 SQL Server 版本。 @thekaido,用户实例是我目前想到的。困扰我的是我将如何编写附件,例如,从我的 winforms 应用程序到 SQL Server 的数据库。有什么建议吗? 【参考方案1】:

您可以使用 Sql Server 管理对象 (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;
    


【讨论】:

哇,这让我很开心。其他人都在试图劝阻提问者不要尝试这个解决方案,而你只是随便过来,用一个简短、干净、简洁的代码清单来回答它。恭喜,好先生,您赢得了我的支持。【参考方案2】:

另一种解决方案是使用 SQLite 而不是 SQL Express。如果您使用this solution,您甚至可以继续使用 ADO.NET。 SQLite 数据库只是文件,您的连接字符串可以引用文件路径。当用户想要打开他们的文件时,他们可以选择一个实际的文件。

【讨论】:

【参考方案3】:

我的印象是这个数据库将在本地用户的机器上运行。如果是这种情况,sql server express 通常不是一个好的数据库选择。它是一个服务器级引擎,而不是桌面或进程引擎。相反,您可以使用许多优秀的流程引擎:Sql Server Compact Edition、Sqlite(Jacob 提到)甚至 Access。

【讨论】:

一个 SQL Server 数据库是两个文件(.MDF 和 .LDF)。如果您可以优雅地管理数据库的附加和分离,我看不出有任何不能使用 SQL Server Express 的原因。 msdn.microsoft.com/en-us/library/ms190794.aspx @Robert:sql server 数据库也是机器上作为服务运行的引擎。 只要您避免使用 Access,您就处于领先地位。【参考方案4】:

如果您认为 SQL Server Express 2008 是正确的选择(尽管 sqllite 似乎更适合),我会考虑使用 User Instances,这将允许非管理员按照您的描述从文件中添加数据库。

【讨论】:

【参考方案5】:

本文展示了如何创建新数据库,并将其附加到 SQL Server 数据库实例:

如何:将数据库文件附加到 SQL Server Expresshttp://msdn.microsoft.com/en-us/library/ms165673.aspx

这些文章展示了如何管理现有数据库的附加和分离: 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

【讨论】:

您能否给我一个提示,如何在 Windows 窗体的 C# 代码中实现这一点(例如,使用 ADO.NET)?谢谢。 您必须执行存储过程来创建、附加和分离数据库。要在 C# 中执行此操作,您将使用适当的连接字符串打开一个 SqlConnection 对象,创建一个传递 SqlConnection 对象和附加或分离数据库的存储过程的名称的 SqlCommand 对象,将一些参数对象添加到 SqlCommand 对象,然后使用 ExecuteNonQuery() 执行 SqlCommand。一个完整的例子在这里,大约在页面的中间:c-sharpcorner.com/UploadFile/dclark/InsOutsinCS11302005072332AM/… 谢谢罗伯特。你是最有帮助的。【参考方案6】:

用于 SQL Server 2008 R2 的以下连接字符串。

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

你可以的

  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;
  

感谢哈维先生指出正确的方向。虽然在我的情况下,我必须做出这些小的改变。因为,我用的是windows认证。

【讨论】:

以上是关于在 C# 中创建(按需)SQL Server 2008 Express 数据库的最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:尝试在存储过程中创建视图

确定用户在 SQL Server 中创建的对象

如何在 SQL Server 表中创建图像列并使用 VB 在 ASP.NET 中检索它

sql 在sql server中创建html

在 SQL Server 事务中创建过程

如何使用 SQL Server Management Studio (2008) 在 SQL Server Compact Edition 中创建列