有没有一种简单的方法来validation数据库模式是否正是我期望它使用entity framework?

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

有没有一种简单的方法来validation数据库模式是否正是我期望它使用entity framework?

EF4本身做了一些validation。 如果映射类型包含目标表中不存在的列,则当EF4实现时,它会触发exception。 精细。 但是有一些事情它没有做:它最初不validation整个数据库。 当目标表包含未映射的列时,它不会触发exception。

有没有一种简单的方法可以实现这一目标?

至于您的具体示例,EF无法知道您没有告诉它有关架构的内容。 如果有一个未映射的字段,只要SQL语句(特别是插入)成功对表EF实际上并不关心。 也许该字段已被弃用,但仍需要为某些遗留应用程序保留该字段,或者因为从活动数据库中删除字段是一个痛苦的一半。

我不知道有什么简单的方法,但是你能做到的一种方法(至少对于SqlServer来说)就是让EF为你生成一个创建脚本(我不确定它是否可以为你做,但是NHibernate是这样的也许有一种方法)并使用Sql Server具有的Smo库解析字符串与服务器中的内容。

我一直在使用这个相关的Github存储库的代码审查问题中使用特定的解决方案。

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

编辑

这是相关的代码示例:

public Validation(ADbContext db) { _connectionString = db.Database.Connection.ConnectionString; } private readonly string _connectionString; public ILookup> Run() { // A tolerance to deal with Entity Framework renaming var modelValidation = GetModelProperties(tolerance); var isValid = !modelValidation.Any(v => v.Any(x => x.Count > 0)); if (!isValid) Logger.Activity(BuildMessage(modelValidation)); return modelValidation; } public string BuildMessage(ILookup> modelValidation) { // build a message to be logged } public List GetMissingColumns(IEnumerable props, IEnumerable 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 columns = connection.Query(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> GetModelProperties(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)); }