实体框架CTP 4 - 代码优先自定义数据库初始化程序

时间:2010-10-27 08:57:01

标签: entity-framework code-first ctp4

我想实现自定义数据库初始化策略,以便我可以使用提供的用户ID和密码生成数据库模式并将其应用于EXISTING EMPTY SQL数据库。

不幸的是,内置策略无法提供我正在寻找的内容:

// The default strategy creates the DB only if it doesn't exist - but it does 
// exist so this does nothing
Database.SetInitializer(new CreateDatabaseOnlyIfNotExists<DataContext>());

// Drops and re-creates the database but then this breaks my security mapping and 
// only works if using a “Trusted" connection
Database.SetInitializer(new RecreateDatabaseIfModelChanges<DataContext>());

// Strategy for always recreating the DB every time the app is run. – no good for 
// what I want
Database.SetInitializer(new AlwaysRecreateDatabase<DataContext>());

我已经解决了以下问题,但这不会创建ModelHash,因此我无法使用“context.Database.ModelMatchesDatabase()”来验证是否已创建数据库架构并阻止多次初始化:

public class Initializer : IDatabaseInitializer<DataContext>  
{ 
    Public void InitializeDatabase(DataContext context)  
    {       
         // this generates the SQL script from my POCO Classes
         var sql = context.ObjectContext.CreateDatabaseScript();

         // As expected - when run the second time it bombs out here with "there is already an
         // object named xxxxx in the database"
         context.ObjectContext.ExecuteStoreCommand(sql); 

         this.seed(context)
         context.SaveChanges();
    }
}  

问题:

有谁知道如何获取/创建模型哈希? (这是一个EdmMetadata实体)

-Or -

使用Code First CTP一般有更好的方法吗?

6 个答案:

答案 0 :(得分:24)

我遇到了同样的问题。我没有真正解决它,但我设法运行了一些讨厌的解决方法,所以我可以将我的解决方案部署到AppHarbor;)

它是一个IDatabaseInitializer实现,它不删除数据库,只是核对所有约束和表,然后使用ObjectContext.CreateDatabaseScript()方法生成sql,然后我将它作为storecommand执行。很像问题中的上述实现。

但我还添加了从模型创建哈希的功能并将其保存在db中,当它再次运行时,它会检查当前模型哈希是否与i db匹配。就像真正的代码优先实现一样。

我无法使用上下文中的构建工作.Database.CompatibleWithModel(true) - 但这应该也可以正常工作,并将其视为临时解决方法,应该没问题。

using System;
using System.Data.Entity;
using System.Data.Entity.Database;
using System.Data.Entity.Design;
using System.Data.Entity.Infrastructure;
using System.Data.Metadata.Edm;
using System.Data.Objects;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using System.Linq;

namespace Devtalk
{
    public class DontDropDbJustCreateTablesIfModelChanged<T> : IDatabaseInitializer<T> where T : DbContext
    {
        private EdmMetadata _edmMetaData;

        public void InitializeDatabase(T context)
        {
            ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
            string modelHash = GetModelHash(objectContext);

            if (CompatibleWithModel(modelHash, context, objectContext)) return;

            DeleteExistingTables(objectContext);
            CreateTables(objectContext);

            SaveModelHashToDatabase(context, modelHash, objectContext);
        }

        private void SaveModelHashToDatabase(T context, string modelHash, ObjectContext objectContext)
        {
            if (_edmMetaData != null) objectContext.Detach(_edmMetaData);

            _edmMetaData = new EdmMetadata();
            context.Set<EdmMetadata>().Add(_edmMetaData);

            _edmMetaData.ModelHash = modelHash;
            context.SaveChanges();
        }

        private void CreateTables(ObjectContext objectContext)
        {
            string dataBaseCreateScript = objectContext.CreateDatabaseScript();
            objectContext.ExecuteStoreCommand(dataBaseCreateScript);
        }

        private void DeleteExistingTables(ObjectContext objectContext)
        {
            objectContext.ExecuteStoreCommand(Dropallconstraintsscript);
            objectContext.ExecuteStoreCommand(Deletealltablesscript);
        }

        private string GetModelHash(ObjectContext context)
        {
            var csdlXmlString = GetCsdlXmlString(context).ToString();
            return ComputeSha256Hash(csdlXmlString);
        }

        private bool CompatibleWithModel(string modelHash, DbContext context, ObjectContext objectContext)
        {
            var isEdmMetaDataInStore = objectContext.ExecuteStoreQuery<int>(LookupEdmMetaDataTable).FirstOrDefault();
            if (isEdmMetaDataInStore == 1)
            {            
                _edmMetaData = context.Set<EdmMetadata>().FirstOrDefault();
                if (_edmMetaData != null)
                {
                    return modelHash == _edmMetaData.ModelHash;
                }
            }
            return false;
        }

        private string GetCsdlXmlString(ObjectContext context)
        {
            if (context != null)
            {
                var entityContainerList = context.MetadataWorkspace.GetItems<EntityContainer>(DataSpace.SSpace);
                if (entityContainerList != null)
                {
                    EntityContainer entityContainer = entityContainerList.FirstOrDefault();
                    var generator = new EntityModelSchemaGenerator(entityContainer);
                    var stringBuilder = new StringBuilder();
                    var xmlWRiter = XmlWriter.Create(stringBuilder);
                    generator.GenerateMetadata();
                    generator.WriteModelSchema(xmlWRiter);
                    xmlWRiter.Flush();
                    return stringBuilder.ToString();
                }
            }
            return string.Empty;
        }

        private static string ComputeSha256Hash(string input)
        {
            byte[] buffer = new SHA256Managed().ComputeHash(Encoding.ASCII.GetBytes(input));
            var builder = new StringBuilder(buffer.Length * 2);
            foreach (byte num in buffer)
            {
                builder.Append(num.ToString("X2", CultureInfo.InvariantCulture));
            }
            return builder.ToString();
        }

        private const string Dropallconstraintsscript =
            @"select  
                'ALTER TABLE ' + so.table_name + ' DROP CONSTRAINT ' + so.constraint_name  
                from INFORMATION_SCHEMA.TABLE_CONSTRAINTS so";

        private const string Deletealltablesscript =
            @"declare @cmd varchar(4000)
                declare cmds cursor for 
                Select
                    'drop table [' + Table_Name + ']'
                From
                    INFORMATION_SCHEMA.TABLES

                open cmds
                while 1=1
                begin
                    fetch cmds into @cmd
                    if @@fetch_status != 0 break
                    print @cmd
                    exec(@cmd)
                end
                close cmds
                deallocate cmds";

        private const string LookupEdmMetaDataTable =
            @"Select COUNT(*) 
              FROM INFORMATION_SCHEMA.TABLES T 
              Where T.TABLE_NAME = 'EdmMetaData'";
    }
}

答案 1 :(得分:7)

这是在 AppHarbor 上运行 EF Code First 的最简单方法!

使用EdmMetadata.TryGetModelHash(context)函数检查模型何时与数据库不匹配,并在运行更改脚本后显示需要使用的新代码的错误。

PopulateOnly:仅在数据库为空时创建对象

我以为我会发布我自己的初始化程序版本,我目前正在 appharbor 上使用填充现有数据库。如果数据库不存在,它也会尝试创建,如果检测到更改,它也会尝试 (抱歉还没有自动更新)。我希望有人觉得它很有用。

    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Data.Objects;
    using System.Transactions;

    namespace Deskspace.EntityFramework
    {

        /// <summary> A Database Initializer for appharbor </summary>
        /// <typeparam name="T">Code first context</typeparam>
        public class PopulateOnly<T> : IDatabaseInitializer<T> where T : DbContext
        {
            private EdmMetadata metadata;

            private enum Status
            {
                Compatable,
                Invalid,
                Missing
            }

            /// <summary> Initializer that supports creating or populating a missing or empty database </summary>
            /// <param name="context"> Context to create for </param>
            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<string>( 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";

        }
    }

答案 2 :(得分:5)

只是为@ Luhmann的解决方案做出贡献,这是我的,但稍微改变了以适当地降低FK和PK。

using System.Data.Entity;
using System.Data.Entity.Design;
using System.Data.Entity.Infrastructure;
using System.Data.Metadata.Edm;
using System.Data.Objects;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

namespace SISQuote.Server.Persistence
{
    public class DontDropExistingDbCreateTablesIfModelChanged<T> : IDatabaseInitializer<T> where T : DbContext
    {
        private EdmMetadata edmMetaData;

        public bool TryInitializeDatabase(T context)
        {
            ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
            string modelHash = GetModelHash(objectContext);

            if (CompatibleWithModel(modelHash, context, objectContext))
                return false;

            DeleteExistingTables(objectContext);
            CreateTables(objectContext);
            SaveModelHashToDatabase(context, modelHash, objectContext);

            return true;
        }

        public void InitializeDatabase(T context)
        {
            TryInitializeDatabase(context);
        }

        private void SaveModelHashToDatabase(T context, string modelHash, ObjectContext objectContext)
        {
            if (edmMetaData != null) 
                objectContext.Detach(edmMetaData);

            edmMetaData = new EdmMetadata();
            context.Set<EdmMetadata>().Add(edmMetaData);

            edmMetaData.ModelHash = modelHash;
            context.SaveChanges();
        }

        private void CreateTables(ObjectContext objectContext)
        {
            string dataBaseCreateScript = objectContext.CreateDatabaseScript();
            objectContext.ExecuteStoreCommand(dataBaseCreateScript);
        }

        private void DeleteExistingTables(ObjectContext objectContext)
        {
            objectContext.ExecuteStoreCommand(DeleteAllTablesScript);
        }

        private string GetModelHash(ObjectContext context)
        {
            var csdlXmlString = GetCsdlXmlString(context).ToString();
            return ComputeSha256Hash(csdlXmlString);
        }

        public bool CompatibleWithModel(DbContext context)
        {
            ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
            return CompatibleWithModel(GetModelHash(objectContext), context, objectContext);
        }

        private bool CompatibleWithModel(string modelHash, DbContext context, ObjectContext objectContext)
        {
            var isEdmMetaDataInStore = objectContext.ExecuteStoreQuery<int>(LookupEdmMetaDataTable).FirstOrDefault();
            if (isEdmMetaDataInStore == 1)
            {
                edmMetaData = context.Set<EdmMetadata>().FirstOrDefault();
                if (edmMetaData != null)
                {
                    return modelHash == edmMetaData.ModelHash;
                }
            }
            return false;
        }

        private string GetCsdlXmlString(ObjectContext context)
        {
            if (context != null)
            {
                var entityContainerList = context.MetadataWorkspace.GetItems<EntityContainer>(DataSpace.SSpace);
                if (entityContainerList != null)
                {
                    EntityContainer entityContainer = entityContainerList.FirstOrDefault();
                    var generator = new EntityModelSchemaGenerator(entityContainer);
                    var stringBuilder = new StringBuilder();
                    var xmlWRiter = XmlWriter.Create(stringBuilder);
                    generator.GenerateMetadata();
                    generator.WriteModelSchema(xmlWRiter);
                    xmlWRiter.Flush();
                    return stringBuilder.ToString();
                }
            }
            return string.Empty;
        }

        private static string ComputeSha256Hash(string input)
        {
            byte[] buffer = new SHA256Managed().ComputeHash(Encoding.ASCII.GetBytes(input));
            var builder = new StringBuilder(buffer.Length * 2);
            foreach (byte num in buffer)
            {
                builder.Append(num.ToString("X2", CultureInfo.InvariantCulture));
            }
            return builder.ToString();
        }

        private const string DeleteAllTablesScript =
            @"declare @cmd varchar(4000)

              DECLARE cmds0 CURSOR FOR 
              SELECT 'ALTER TABLE ' + TABLE_NAME + ' DROP CONSTRAINT ' + CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'

              DECLARE cmds1 CURSOR FOR 
              SELECT 'ALTER TABLE ' + TABLE_NAME + ' DROP CONSTRAINT ' + CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS

              DECLARE cmds2 CURSOR FOR 
              SELECT 'TRUNCATE TABLE ' + TABLE_NAME FROM INFORMATION_SCHEMA.TABLES

              DECLARE cmds3 CURSOR FOR 
              SELECT 'DROP TABLE [' + TABLE_NAME + ']' FROM INFORMATION_SCHEMA.TABLES

              open cmds0
              while 1=1
              begin
                  fetch cmds0 into @cmd
                  if @@fetch_status != 0 break
                  print @cmd
                  exec(@cmd)
              end
              close cmds0
              deallocate cmds0

              open cmds1
              while 1=1
              begin
                  fetch cmds1 into @cmd
                  if @@fetch_status != 0 break
                  print @cmd
                  exec(@cmd)
              end
              close cmds1
              deallocate cmds1

              open cmds2
              while 1=1
              begin
                  fetch cmds2 into @cmd
                  if @@fetch_status != 0 break
                  print @cmd
                  exec(@cmd)
              end
              close cmds2
              deallocate cmds2

              open cmds3
              while 1=1
              begin
                  fetch cmds3 into @cmd
                  if @@fetch_status != 0 break
                  print @cmd
                  exec(@cmd)
              end
              close cmds3
              deallocate cmds3";

        private const string LookupEdmMetaDataTable =
            @"Select COUNT(*) 
              FROM INFORMATION_SCHEMA.TABLES T 
              Where T.TABLE_NAME = 'EdmMetaData'";
    }
}

答案 3 :(得分:4)

我对这个问题略有不同。这似乎是分享结果的好地方。

我想只创建数据库中尚不存在的表。这样做的好处是能够在不删除数据库其余部分的情况下推出新表。

如果在继承链中有多个数据上下文,这也会有所帮助。例如,如果将应用程序拆分为不同的程序集。您可能在“核心”模块中具有数据上下文,然后在附加模块的不同程序集中继承它。此配置工作正常,但内置的Drop / Create初始值设定项不喜欢它,因为模型哈希值一直在变化。通过检查表存在,初始化需要稍长,但是你没有这些问题。

无论如何,这是代码:

/// <summary>
/// Database Initializer to create tables only if they don't already exist.
/// It will never drop the database.  Does not check the model for compatibility.
/// </summary>
/// <typeparam name="TContext">The data context</typeparam>
public class CreateTablesOnlyIfTheyDontExist<TContext> : IDatabaseInitializer<TContext>
  where TContext : DataContext
{
  public void InitializeDatabase(TContext context)
  {
    using (new TransactionScope(TransactionScopeOption.Suppress))
    {
      // If the database doesn't exist at all then just create it like normal.
      if (!context.Database.Exists())
      {
        context.Database.Create();
        return;
      }

      // get the object context
      var objectContext = ((IObjectContextAdapter)context).ObjectContext;

      // get the database creation script
      var script = objectContext.CreateDatabaseScript();


      if (context.Database.Connection is SqlConnection)
      {
        // for SQL Server, we'll just alter the script

        // add existance checks to the table creation statements
        script = Regex.Replace(script,
          @"create table \[(\w+)\]\.\[(\w+)\]",
          "if not exists (select * from INFORMATION_SCHEMA.TABLES " +
          "where TABLE_SCHEMA='$1' and TABLE_NAME = '$2')\n$&");

        // add existance checks to the table constraint creation statements
        script = Regex.Replace(script,
          @"alter table \[(\w+)\]\.\[(\w+)\] add constraint \[(\w+)\]",
          "if not exists (select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS " +
          "where TABLE_SCHEMA='$1' and TABLE_NAME = '$2' " +
          "and CONSTRAINT_NAME = '$3')\n$&");

        // run the modified script
        objectContext.ExecuteStoreCommand(script);
      }
      else if (context.Database.Connection is SqlCeConnection)
      {
        // SQL CE doesn't let you use inline existance checks,
        // so we have to parse each statement out and check separately.

        var statements = script.Split(new[] { ";\r\n" },
                        StringSplitOptions.RemoveEmptyEntries);
        foreach (var statement in statements)
        {
          var quoteSplitStrings = statement.Split('"');
          if (statement.StartsWith("CREATE TABLE"))
          {
            // Create a table if it does not exist.
            var tableName = quoteSplitStrings[1];
            const string sql = 
              "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES " +
              "WHERE TABLE_NAME='{0}'"
            var checkScript = string.Format(sql, tableName);
            if (objectContext.ExecuteStoreQuery<int>(checkScript).First() == 0)
              objectContext.ExecuteStoreCommand(statement);
          }
          else if (statement.Contains("ADD CONSTRAINT"))
          {
            // Add a table constraint if it does not exist.
            var tableName = quoteSplitStrings[1];
            var constraintName = quoteSplitStrings[3];
            const string sql = 
              "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS " +
              "WHERE TABLE_NAME='{0}' AND CONSTRAINT_NAME='{1}'";
            var checkScript = string.Format(sql, tableName, constraintName);
            if (objectContext.ExecuteStoreQuery<int>(checkScript).First() == 0)
              objectContext.ExecuteStoreCommand(statement);
          }
          else
          {
            // Not sure what else it could be. Just run it.
            objectContext.ExecuteStoreCommand(statement);
          }
        }
      }
      else
      {
        throw new InvalidOperationException(
          "This initializer is only compatible with SQL Server or SQL Compact Edition"
          );
      }
    }
  }
}

答案 4 :(得分:1)

我也在寻找一个好的解决方案,因为godaddy不允许删除/创建数据库,因此没有创建表。由于较新版本的Entity Framework已经废弃了EDMData,我修改了Alex的代码以查看DropMeToRecreateDatabase表是否存在,如果它不存在,它会删除所有表并重新创建新表。

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Linq;

namespace LadyTreble.DatabaseInitializer
{

    public class DontDropExistingDbCreateTablesIfTableDropped<T> : IDatabaseInitializer<T> where T : DbContext
    {
        public bool TryInitializeDatabase(T context)
        {
            var objectContext = ((IObjectContextAdapter)context).ObjectContext;
            if (objectContext.ExecuteStoreQuery<int>(GetTableCount).FirstOrDefault() == 0)
            {
                this.DeleteExistingTables(objectContext);
                this.CreateTables(objectContext);
            }
            return true;
        }

        public void InitializeDatabase(T context)
        {
            this.TryInitializeDatabase(context);
        }

        private void CreateTables(ObjectContext objectContext)
        {
            string dataBaseCreateScript = objectContext.CreateDatabaseScript();
            objectContext.ExecuteStoreCommand(dataBaseCreateScript);
        }

        private void DeleteExistingTables(ObjectContext objectContext)
        {

            objectContext.ExecuteStoreCommand(DeleteAllTablesScript);
        }

        private const string DeleteAllTablesScript =
            @"declare @cmd varchar(4000)

              DECLARE cmds0 CURSOR FOR 
              SELECT 'ALTER TABLE ' + TABLE_NAME + ' DROP CONSTRAINT ' + CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'

              DECLARE cmds1 CURSOR FOR 
              SELECT 'ALTER TABLE ' + TABLE_NAME + ' DROP CONSTRAINT ' + CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS

              DECLARE cmds2 CURSOR FOR 
              SELECT 'TRUNCATE TABLE ' + TABLE_NAME FROM INFORMATION_SCHEMA.TABLES

              DECLARE cmds3 CURSOR FOR 
              SELECT 'DROP TABLE [' + TABLE_NAME + ']' FROM INFORMATION_SCHEMA.TABLES

              open cmds0
              while 1=1
              begin
                  fetch cmds0 into @cmd
                  if @@fetch_status != 0 break
                  print @cmd
                  exec(@cmd)
              end
              close cmds0
              deallocate cmds0

              open cmds1
              while 1=1
              begin
                  fetch cmds1 into @cmd
                  if @@fetch_status != 0 break
                  print @cmd
                  exec(@cmd)
              end
              close cmds1
              deallocate cmds1

              open cmds2
              while 1=1
              begin
                  fetch cmds2 into @cmd
                  if @@fetch_status != 0 break
                  print @cmd
                  exec(@cmd)
              end
              close cmds2
              deallocate cmds2

              open cmds3
              while 1=1
              begin
                  fetch cmds3 into @cmd
                  if @@fetch_status != 0 break
                  print @cmd
                  exec(@cmd)
              end
              close cmds3
              deallocate cmds3

             CREATE TABLE DropMeToRecreateDatabase(id int IDENTITY(1,1) NOT NULL)";

        private const string GetTableCount =
            @"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES T WHERE T.TABLE_NAME = 'DropMeToRecreateDatabase'";
    }

}

答案 5 :(得分:-2)

Entity Designer Database Generation Power Pack会这样做。不确定它是否适用于Code First,但值得一试。