【问题标题】:Is there an easy way to verify whether or not the database schema is exactly what I expect it to be using Entity Framework?有没有一种简单的方法来验证数据库架构是否正是我期望它使用实体框架的方式?
【发布时间】:2011-07-24 19:47:57
【问题描述】:

我希望我的应用程序在启动时验证数据库一致性。

是否有一种简单的方法来验证数据库架构是否正是我期望它使用 Entity Framework 的方式?

EF4 本身会进行一些验证。如果映射类型包含目标表中不存在的列,则在 EF4 实现时会触发异常。美好的。但是有些事情它没有做:它首先不验证整个数据库。当目标表包含未映射的列时,不会触发异常。

有没有简单的方法可以做到这一点?

【问题讨论】:

  • @tucaz: SQL Server 但解决方案应该支持多个数据库,即使我必须编写一些特定于每个 DBMS 的代码

标签: c# .net entity-framework validation entity-framework-4


【解决方案1】:

至于您的具体示例,EF 无法知道您没有告诉它有关架构的内容。如果有一个未映射的字段,只要 SQL 语句(尤其是插入)成功地针对表 EF 真的不在乎。也许该字段已被弃用,但仍必须为某些旧版应用程序保留它,或者因为从活动数据库中删除字段很麻烦。

【讨论】:

    【解决方案2】:

    我不知道任何简单的方法,但是您可以做到的一种方法(至少对于 SqlServer)是让 EF 为您生成一个创建脚本(我不确定它是否能够为您做到这一点,但是NHibernate 所以也许有办法)并使用 Sql Server 拥有的 Smo 库根据服务器中的内容解析字符串。

    【讨论】:

      【解决方案3】:

      我一直在 code review question 中为此使用特定的解决方案,并与此相关的 Github repository

      我选择不使用 MetadataWorkspace,但可以修改代码以使用它而不是反射。

      编辑

      以下是相关代码示例:

      public Validation(ADbContext db)
      {
          _connectionString = db.Database.Connection.ConnectionString;
      }
      
      private readonly string _connectionString;
      
      public ILookup<string, List<string>> Run()
      {
          // A tolerance to deal with Entity Framework renaming
          var modelValidation = GetModelProperties<ADbContext>(tolerance);
          var isValid = !modelValidation.Any(v => v.Any(x => x.Count > 0));
          if (!isValid)
              Logger.Activity(BuildMessage(modelValidation));
          return modelValidation;
      }
      
      public string BuildMessage(ILookup<string, List<string>> modelValidation)
      {
          // build a message to be logged
      } 
      
      public List<string> GetMissingColumns(IEnumerable<string> props, IEnumerable<string> columns, int tolerance)
      {
          // compare whether the entity properties have corresponding columns in the database
          var missing = props.Where(p => !columns.Any(c => p.StartsWith(c) && Math.Abs(c.Length - p.Length) <= tolerance)).ToList();
          return missing;
      }
      
      public string[] GetSQLColumnNames(Type t)
      {
          SqlConnection connection = new SqlConnection(_connectionString);
          var table = t.Name;
          DynamicParameters dparams = new DynamicParameters();
          dparams.Add("Table", table);
          var query = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @Table ";
          // Using dapper to retrieve list of columns from that table
          List<string> columns = connection.Query<string>(query, dparams).ToList();
          return columns.ToArray();
      }
      
      static string[] GetEntityPropertyNames(Type t)
      {
          var properties = t.GetProperties(BindingFlags.Instance | BindingFlags.Public)
                  .Where(p => p.CanRead && !p.PropertyType.FullName.Contains("My.Namespace") && !p.PropertyType.FullName.Contains("Collection"))
                  .Select(p => p.Name)
                  .ToArray();
          // these conditions excludes navigation properties: !p.PropertyType.FullName.Contains("My.Namespace") && !p.PropertyType.FullName.Contains("Collection")
          return properties;
      }
      
      ILookup<string, List<string>> GetModelProperties<T>(int tolerance, T source = default(T))
      {
          var properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
                  .Where(p => p.PropertyType.IsGenericType)
                  .Select(p => p.PropertyType.GetGenericArguments()[0])
                  .Select(p => new
                  {
                      Entity = p.Name,
                      Properties = GetEntityPropertyNames(p),
                      Columns = GetSQLColumnNames(p),
                  })
                  .ToArray();
      
          return properties.ToLookup(p => p.Entity, p => GetMissingColumns(p.Properties, p.Columns, tolerance));
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-04
        • 1970-01-01
        • 2016-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多