views:

250

answers:

5

Hi all.

The purpose is to handle the user's data (you can call them project, document, file, or whatever) in a brand new SQL Server 2008 Express database. The data are expected to occupy much less space than the 4GB available with the express edition (which is also free to distribute).

E.g., each time the user selects File->New command, a new empty database will be created at the specified location. On the other hand, a similar command, File->Open must provide support to retrieve the list of the databases to select one for opening.

So, the following issues must be resolved: a) The application must be able to create the connection string and attach the database to SQL Server 2008 Express through code (C#) b) The application must be able to retrieve (again through code) a list with all the available databases, to give the user a chance to select one to open.

I think it would be helpful to have a template database in resources and copy it in the location specified by the user.

Do you think it is a working solution? Do you have any suggestions?

A: 

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.

Jacob
+1  A: 

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.

Joel Coehoorn
A SQL Server database is two files (.MDF and .LDF). If you can manage Attaching and Detaching the databases elegantly, I don't see any reason why SQL Server Express couldn't be used. http://msdn.microsoft.com/en-us/library/ms190794.aspx
Robert Harvey
@Robert: A sql server database is also the engine that runs as a service on the machine.
Joel Coehoorn
Just so long as you avoid Access, you're ahead of the game.
Steven Sudit
A: 

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.

thekaido
+1  A: 

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

Robert Harvey
Can you give me a hint how this can be implemented in C# code from a windows form (e.g., using ADO.NET)? Thank you.
ileon
You have to execute the stored procedures to create, attach, and detach databases. To do this in C#, you would open a SqlConnection object with an appropriate connection string, create a SqlCommand object passing the SqlConnection object and the name of the stored procedure that attaches or detaches the database, add some parameter objects to the SqlCommand Object, and execute the SqlCommand using ExecuteNonQuery(). A complete example is here, about halfway down the page: http://www.c-sharpcorner.com/UploadFile/dclark/InsOutsinCS11302005072332AM/InsOutsinCS.aspx
Robert Harvey
Thank you Robert. You've been most helpful.
ileon
+2  A: 

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

}
Robert Harvey