Есть ли простой способ проверить, является ли схема базы данных именно такой, как я ожидаю, используя Entity Framework? - PullRequest
4 голосов
/ 29 марта 2011

Я хочу, чтобы мое приложение проверяло согласованность базы данных во время запуска.

Существует ли простой способ проверить, соответствует ли схема базы данных именно той, которую я ожидаю, используя Entity Framework?

EF4 сам выполняет некоторую проверку.Если сопоставленный тип содержит столбец, который не существует в целевой таблице, когда EF4 материализуется, он вызывает исключение.Хорошо.Однако есть некоторые вещи, которые он не делает: он сначала не проверяет всю базу данных.Это не вызывает исключение, когда целевая таблица содержит столбец, который не сопоставлен.

Есть ли простой способ сделать это?

Ответы [ 3 ]

2 голосов
/ 29 марта 2011

Что касается вашего конкретного примера, EF не может знать, что вы не говорите о схеме. Если есть поле, которое не отображается, пока операторы SQL (особенно вставки) успешно работают с таблицей, EF действительно не заботится. Возможно, это поле устарело, но его все равно нужно сохранить для какого-либо устаревшего приложения или потому, что удаление поля из активной БД - это полторы боли.

0 голосов
/ 10 августа 2016

Я использовал конкретное решение для этого в вопросе проверки кода с этим связанным Github-репозиторием .

Я решил не использовать MetadataWorkspace, но код можно изменить, чтобы использовать его вместо отражения.

EDIT

Вот соответствующий пример кода:

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));
}
0 голосов
/ 29 марта 2011

Я не знаю простых способов, но один из способов, которым вы могли бы это сделать (по крайней мере, для SqlServer), - создать EF для вас сценарий создания (я не уверен, что он сможет сделать это за вас, ноNHibernate так, может быть, есть способ) и проанализируйте строку с тем, что у вас есть на сервере, используя библиотеку Smo, что Sql Server имеет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...