实体框架 CTP 4 - 代码优先自定义数据库初始值设定项

2024-05-09

我想实现自定义数据库初始化策略,以便我可以生成数据库架构并使用提供的用户 ID 和密码将其应用到现有的空 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,所以我无法使用“上下文.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 是否有更好的方法来执行此操作?


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

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

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

我无法让它与 context.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'";
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实体框架 CTP 4 - 代码优先自定义数据库初始值设定项 的相关文章

随机推荐

  • serde/bincode 如何序列化字节数组?

    这段代码完全按照我的要求序列化了一个 32 字节的数组 derive Debug Clone Serialize Deserialize PartialEq Eq PartialOrd Ord struct Hash u8 32 let h
  • 如何使 WordPress 中的自定义模板充当受密码保护的页面?

    我正在使用自定义模板构建一个页面 问题是 我需要此页面受密码保护 或者至少可供登录用户访问 但即使我在 WordPress 管理的新页面部分中将其设置为此类 私人 密码保护 它也不会显示菜单项和内容 如果是私有的 或者它会立即显示页面内容
  • 如何在jquery中创建一个全局函数,并从另一个加载的页面调用它

    如何在 jquery 中声明全局函数 如何从使用 jquery 的 load 函数加载到该页面上的某个 div 中的页面调用它 该功能很简单第 1 个子页面 main links 1st sub page myfun function is
  • 合并字符数组中的最小重复次数

    假设我有两个数组 我想合并它们 以便合并后的数组具有最小重复次数 例如 x x 是重复 arr1 x d d m f m arr2 d d x f f m 唯一的条件是在合并数组中 元素来自arr1 and arr2必须出现在各自的订单中a
  • 将 stdout 作为命令行 util 的文件名传递?

    我正在使用一个命令行实用程序 该实用程序需要传递文件名以将输出写入 例如 foo o output txt 它唯一写入的东西stdout是一条消息 表明它运行成功 我希望能够通过管道传输写入的所有内容output txt到另一个命令行实用程
  • 为什么 Excel 有时会在工作表名称中添加 $?

    我有时但并非总是发现 Excel 会放置一个 位于工作表名称末尾 但在 Excel 中看不到 只有在尝试使用 C 将其导入 SQL Server 时才可见 我遇到过很多不同的情况 它保留了原始工作表 但也创建了第二个空的 隐藏 工作表 其中
  • Laravel 雄辩的 withCount() 应该比 with() 慢

    所以我问这个的原因是在我当前的应用程序中withCount 与仅通过以下方式获取关系的所有数据相比 响应时间几乎增加了三倍with 并只是从前端获取长度 javascript 我认为使用的要点withCount 是为了加快查询速度 但也许我
  • 在 WooCommerce 3.3 中使用 Google Map API 计算结帐距离

    我已经发布几个月前有类似的问题 https stackoverflow com questions 46348735 calculated distance shipping cart fee via google api in wooco
  • 如何将 currentTimeMillis 转换为可读的日期格式? [复制]

    这个问题在这里已经有答案了 我想用currentTimeMillis两次 这样我就可以计算持续时间 但我也想以用户可读的格式显示时间和日期 我遇到了麻烦currentTimeMillis有利于计算 但我看不到内置函数可以转换为合适的时间或时
  • Spring @Value 添加验证小于

    我使用以下属性值注入 我如何向此操作添加小于验证 我的意思是我想设置一个验证user maxpassiveday可以说 财产价值不得低于 100 Value user maxpassiveday int maxpassiveday 使用Sp
  • 如何使用 msgpack 进行读写?

    如何序列化 反序列化字典data with msgpack http msgpack org The Python 文档 http msgpack python readthedocs io en latest badge latest似乎
  • 嵌套对象的 AJV 模式验证

    函数返回的对象看起来像这样 answer vehicle type 1 message Car model VW color red 答案 对象始终存在 其他字段基于 vehicle type E g 如果vehicle type 1 则有
  • 按自定义字母顺序对数组进行排序

    如何对这样的数组进行排序 apple very auto tom tim violet 要按 v a t x b 等排序 不按字母顺序 violet very auto tom tim 在脚本中 我会做这样的事情 myArray sort
  • UISearchBAR 范围Bar 色调颜色

    有没有人设法为 UISearchBar 的范围栏部分着色 它有一个 TintColor 属性 但设置它不会影响附加的范围栏 UISegmentedControl 我在吧台上有一个手柄可以给它着色 但似乎不起作用 即 for id subvi
  • 单线程公寓问题

    从我的主窗体中 我调用以下命令来打开一个新窗体 MyForm sth new MyForm sth show 一切都很好 但是这个表单有一个组合框 当我将其 AutoCompleteMode 切换为建议和追加时 我在显示表单时遇到了这个异常
  • SQL Server 全文搜索 - 是否可以在单词中间进行搜索?

    我的数据库有全文搜索 是否可以在单词中间搜索某些文本 例如 我有一个描述列 其中包含以下文本 Revolution 是否可以搜索 EVO 并让它在 革命 一词中找到它 或者我是否一直在做 LIKE SELECT FROM Table WHE
  • 用于测试的嵌入式 H2 数据库的 Spring 配置

    使用 Spring 进行集成测试的配置是什么样的 嵌入式 h2 数据源 http www h2database com html main html以及可选的 JUnit 我第一次尝试单连接数据源 http static springsou
  • 提交表格并上传带有请求的文件

    我正在努力提交特定的表格蟒蛇请求 http www python requests org 我想使用它的网站上的其他表单工作正常 我可以提交登录表单等 这只是我遇到问题的文件上传 显然 提交表单效果很好 因为我从网站收到一条消息 说 请返回
  • 如何滚动到 jQuery Mobile 中的页面元素?

    我有一个很长的 jQuery 移动页面 并且想在页面加载后滚动到该页面中间的元素 到目前为止 我已经尝试了一些事情 最成功的是 jQuery document bind mobileinit function var target if t
  • 实体框架 CTP 4 - 代码优先自定义数据库初始值设定项

    我想实现自定义数据库初始化策略 以便我可以生成数据库架构并使用提供的用户 ID 和密码将其应用到现有的空 SQL 数据库 不幸的是 内置策略无法提供我正在寻找的内容 The default strategy creates the DB o