4

I've searched the internet thoroughly but couldn't find a clear answer to the problem. I have got the aspnet.db database. But i want to add my own tables and data to this database. If i try to connect to it with the connection string:

<add name ="ToernooiCompanionDBContext" connectionString ="Data Source= .\SQLEXPRESS; Integrated Security = SSPI; Trusted_Connection=True; Initial Catalog= aspnetdb"  providerName ="System.Data.SqlClient"/>

A new database will be created (aspnetdb.mdf) in C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA.

I want the database (which is automatically generated by codefirst) to merge with the existing one in my APP_DATA folder. What am I doing wrong?

I've tried adding AttachDbFilename=|DataDirectory|aspnetdb.mdf and User Instance=true to my connection string, or using the LocalSqlServer connection string which is defined in machine.config, but in all cases this overwrites the existing database. If I remove Initial Catalog=aspnetdb then I get an error that the initial catalog is needed.

tereško
  • 58,060
  • 25
  • 98
  • 150
Cissmayazz
  • 2,195
  • 3
  • 15
  • 10
  • Whenever I'm struggling for connection string syntax, I head to www.connectionstrings.com There's a few examples for SQL2008 regarding "Attach a database file" here: http://www.connectionstrings.com/sql-server-2008 I'm not sure what you mean by "merge with the existing one". You're trying to combine the schema and data of two databases into one? It sounds like there's two issues here. 1. "Merge" database, 2. Get the connection string right. – Snixtor May 11 '12 at 00:30

2 Answers2

4

I had the same problem but this link got me on the track to something that worked at least for me. I hope this helps someone at least! :)

  1. Create a database
  2. Add the aspnet tables to the new database
  3. Fix the database connections in web.config so they point to the same database
  4. Write some sql that removes all tables except the ones that start with "aspnet_"
  5. Add the sql to the database initializer you write by your self
  6. Add a call to the database initializer in Global.asax.cs

1. Create a database

I usually do this with SQL Server Management Studio. The database I used for this example code is SQL Server 2008R2 but I have done the same with SQL Server Express that you use.

2. Add the aspnet tables to the new database

I use the following tool which if you use it without any command line arguments works like a wizard. %windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regsql.exe

3. Fix the database connections so they point to the same database

The following two lines are from the test application I made. Notice that the name of the second connectionstring (MyHealthContext) is identical to the name of the DbContext I am using for my code first classes.

DbContext:

public class MyHealthContext : DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<PersonAttribute> PeopleAttributes { get; set; }
}

Web.config

<add name="ApplicationServices" connectionString="Server=localhost\mssql2008r2;Database=MyHealth;Integrated Security=True;" providerName="System.Data.SqlClient"/> 
<add name="MyHealthContext" connectionString="Server=localhost\mssql2008r2;Database=MyHealth;Integrated Security=True;" providerName="System.Data.SqlClient"/>

4. SQL that removes all but the aspnetdb-tables

DECLARE @cmdDropConstraints VARCHAR(4000)
DECLARE @cmdDropTables      VARCHAR(4000)

-- ======================================================================
-- DROP ALL THE FOREIGN KEY CONSTRAINTS FROM THE TABLES WE WANT TO DROP
-- ======================================================================
DECLARE cursorDropConstraints CURSOR FOR 
    SELECT 
        'ALTER TABLE ['+ s.name + '].[' + t.name + '] DROP CONSTRAINT [' + f.name +']' 
    FROM 
        sys.foreign_keys f 
        INNER JOIN sys.tables t ON f.parent_object_id=t.object_id 
        INNER JOIN sys.schemas s ON t.schema_id=s.schema_id 
    WHERE 
        t.is_ms_shipped=0
        AND t.name NOT LIKE 'aspnet_%'
        AND t.name <> 'sysdiagrams'

OPEN cursorDropConstraints
WHILE 1=1
BEGIN
    FETCH cursorDropConstraints INTO @cmdDropConstraints
    IF @@fetch_status != 0 BREAK
    EXEC(@cmdDropConstraints)
END
CLOSE cursorDropConstraints
DEALLOCATE cursorDropConstraints;

-- ======================================================================
-- DROP ALL THE RELEVANT TABLES SO THAT THEY CAN BE RECREATED
-- ======================================================================
DECLARE cursorDropTables CURSOR FOR 
    SELECT 
        'DROP TABLE [' + Table_Name + ']'
    FROM 
        INFORMATION_SCHEMA.TABLES
    WHERE
        Table_Name NOT LIKE 'aspnet_%'
        AND TABLE_TYPE <> 'VIEW'
        AND TABLE_NAME <> 'sysdiagrams'

OPEN cursorDropTables
WHILE 1=1
BEGIN
    FETCH cursorDropTables INTO @cmdDropTables
    IF @@fetch_status != 0 BREAK
    EXEC(@cmdDropTables)
END
CLOSE cursorDropTables
DEALLOCATE cursorDropTables;

5. Code for the database initializer:

Replace the "SQL CODE GOES HERE" below with the sql from step 4

public class MyHealthInitializerDropCreateTables : IDatabaseInitializer<MyHealthContext>
{
    public void InitializeDatabase(MyHealthContext context)
    {
        bool dbExists;
        using (new TransactionScope(TransactionScopeOption.Suppress))
        {
            dbExists = context.Database.Exists();
        }

        if (dbExists)
        {
            // Remove all tables which are specific to the MyHealthContext (not the aspnetdb tables)
            context.Database.ExecuteSqlCommand(@"SQL CODE GOES HERE");

            // Create all tables which are specific to the MyHealthContext (not the aspnetdb tables)
            var dbCreationScript = ((IObjectContextAdapter)context).ObjectContext.CreateDatabaseScript();
            context.Database.ExecuteSqlCommand(dbCreationScript);

            Seed(context);
            context.SaveChanges();
        }
        else
        {
            throw new ApplicationException("No database instance");
        }
    }

    protected virtual void Seed(MyHealthContext context)
    {
        //TODO: Add code for seeding your database with some initial data...
    }
}

6. Code that hooks in your new database initializer

To make sure that the custom database initializer isn't accidentily run in the production environment i added a #if DEBUG statement since I always compile my code in release mode before publishing.

    protected void Application_Start()
    {
        //TODO: Comment out this database initializer(s) before going into production
        #if DEBUG
        Database.SetInitializer<MyHealthContext>(new MyHealthInitializerDropCreateTables()); // Create new tables in an existing database
        #endif

        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }
Sandman
  • 795
  • 7
  • 16
0
  1. Open ASPNetDB db in sql server by attaching as new database
  2. Make Creation scripts of tables / Stored proce3dures from ASPNetDB and run in your own database to create tables in your database
  3. Open web.config of your application and attach application to your own database. Copy the name of connection string
  4. Go to membership area and replace connectionstring name with copied one
  5. Do above step with area as well
Rup
  • 33,765
  • 9
  • 83
  • 112
Tanveer
  • 1,937
  • 3
  • 24
  • 40
  • But that'll no longer be using a SQL Server Express attach-by-file database will it? I'm not sure that's what he wanted. – Rup May 21 '12 at 08:45