Entity Framework CTP 4 - Code First Custom Database Initializer

后端 未结 6 651
傲寒
傲寒 2020-11-28 23:53

I would like to implement a custom database initialization strategy so that I can generate the database schema and apply it to an EXISTING EMPTY SQL database using a supplie

6条回答
  •  情歌与酒
    2020-11-29 00:32

    This is the easiest way to get EF Code First running on AppHarbor!

    Using the EdmMetadata.TryGetModelHash(context) function to check when the model doesn't match the database and showing an error with the new code that needs to be used after you run alteration scripts.

    PopulateOnly : Only creates objects when the database is empty

    I thought I'd post my own version of the Initializer which I'm currently using on appharbor to populate an existing database. It will also try to do a create if the database doesn't exists and throws if a change is detected (sorry no automatic updating yet). I hope someone finds it useful.

        using System;
        using System.Data.Entity;
        using System.Data.Entity.Infrastructure;
        using System.Data.Objects;
        using System.Transactions;
    
        namespace Deskspace.EntityFramework
        {
    
            ///  A Database Initializer for appharbor 
            /// Code first context
            public class PopulateOnly : IDatabaseInitializer where T : DbContext
            {
                private EdmMetadata metadata;
    
                private enum Status
                {
                    Compatable,
                    Invalid,
                    Missing
                }
    
                ///  Initializer that supports creating or populating a missing or empty database 
                ///  Context to create for 
                public void InitializeDatabase(T context)
                {
                    // Get metadata hash
                    string hash = EdmMetadata.TryGetModelHash(context);
    
                    bool exists;
                    using (new TransactionScope( TransactionScopeOption.Suppress )) {
                        exists = context.Database.Exists();
                    }
    
                    if (exists) {
    
                        ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
    
                        var dbHash = GetHashFromDatabase( objectContext );
    
                        Status compatability = 
                                string.IsNullOrEmpty( dbHash )? 
                            Status.Missing : 
                                (dbHash != hash)? 
                            Status.Invalid :
                            Status.Compatable;
    
                        if (compatability == Status.Missing) {
    
                            // Drop all database objects
                            ClearDatabase( objectContext );
    
                            // Recreate database objects
                            CreateTables( objectContext );
    
                            // Save the new hash
                            SaveHash( objectContext,  hash );
    
                        } else if (compatability == Status.Invalid) {
    
                            throw new Exception( 
                                "EdmMetadata does not match, manually update the database, expected: " + 
                                Environment.NewLine + 
                                "<[(" + hash + ")}>"
                            );
                        }
                    } else {
                        context.Database.Create();
                        context.SaveChanges();
                    }
                }
    
                private void ClearDatabase(ObjectContext objectContext)
                {
                    objectContext.ExecuteStoreCommand( DropAllObjects );
                }
    
                private void CreateTables(ObjectContext objectContext)
                {
                    string dataBaseCreateScript = objectContext.CreateDatabaseScript();
                    objectContext.ExecuteStoreCommand( dataBaseCreateScript );
                }
    
                private void SaveHash(ObjectContext objectContext, string hash)
                {
                    objectContext.ExecuteStoreCommand( string.Format(UpdateEdmMetaDataTable, hash.Replace( "'", "''" )) );
                }
    
                private string GetHashFromDatabase(ObjectContext objectContext)
                {
                    foreach (var item in objectContext.ExecuteStoreQuery( GetEdmMetaDataTable )) {
                        return item;
                    }
    
                    return string.Empty;
                }
    
                private const string UpdateEdmMetaDataTable = @"
        Delete From EdmMetadata;
        Insert Into EdmMetadata (ModelHash) Values ('{0}');";
    
                private const string GetEdmMetaDataTable = @"
        If Exists (Select * From INFORMATION_SCHEMA.TABLES tables where tables.TABLE_NAME = 'EdmMetaData')
            Select Top 1 ModelHash From EdmMetadata;
        Else
            Select '';";
    
                private const string DropAllObjects = @"
        declare @n char(1)
        set @n = char(10)
    
        declare @stmt nvarchar(max)
    
        -- procedures
        select @stmt = isnull( @stmt + @n, '' ) +
            'drop procedure [' + name + ']'
        from sys.procedures
    
        -- check constraints
        select @stmt = isnull( @stmt + @n, '' ) +
            'alter table [' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
        from sys.check_constraints
    
        -- functions
        select @stmt = isnull( @stmt + @n, '' ) +
            'drop function [' + name + ']'
        from sys.objects
        where type in ( 'FN', 'IF', 'TF' )
    
        -- views
        select @stmt = isnull( @stmt + @n, '' ) +
            'drop view [' + name + ']'
        from sys.views
    
        -- foreign keys
        select @stmt = isnull( @stmt + @n, '' ) +
            'alter table [' + object_name( parent_object_id ) + '] drop constraint [' + name + ']'
        from sys.foreign_keys
    
        -- tables
        select @stmt = isnull( @stmt + @n, '' ) +
            'drop table [' + name + ']'
        from sys.tables
    
        -- user defined types
        select @stmt = isnull( @stmt + @n, '' ) +
            'drop type [' + name + ']'
        from sys.types
        where is_user_defined = 1
    
        exec sp_executesql @stmt";
    
            }
        }
    

提交回复
热议问题