Динамическое отображение флюентов с EF4.1 - PullRequest
0 голосов
/ 19 марта 2012

Я хочу динамически создать свою модель данных для работы с некоторыми существующими классами и настраиваемым файлом сопоставления XML, потому что у меня много существующих таблиц и множество существующих бизнес-классов (может быть, я сумасшедший, я не знаю).

Для свойств, которые используют разные имена столбцов или не соответствуют существующим столбцам, я хочу вызвать .Ignore () и .HasColumnName (), но я хочу сделать это двоично.

Итак, я хочу иметь возможность совершать подобные вызовы, но я хочу делать их динамически на основе отражения и XML-файла конфигурации с использованием Linq.Expressions (которым у меня никогда не было повода):

modelBuilder.Entity<Product>().Property(p => p.QuantityInStock).HasColumnName("UnitsInStock");

или

modelBuilder.Entity<Product>().Ignore(p => p.QuantityInStock);

Это то, что я пытаюсь (в конечном итоге я обращусь к своей карте XML, чтобы определить, какие свойства сопоставлять, а какие игнорировать):

Type entityType = typeof(Product);

var config = modelBuilder.GetType().GetMethod("Entity")
    .MakeGenericMethod(entityType)
    .Invoke(modelBuilder, null);

var ignore = config.GetType().GetMethod("Ignore").MakeGenericMethod(entityType);

var paramEx = Expression.Parameter(entityType);
var lambdaEx = Expression.Lambda(Expression.Property(paramEx, "QuantityInStock"), paramEx);

ignore.Invoke(config, new[] { lambdaEx });

Но мое лямбда-выражение неверно:

Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[ConsoleApplication2.Product,System.Int16]]' 
cannot be converted to type 
'System.Linq.Expressions.Expression`1[System.Func`2[ConsoleApplication2.Product,ConsoleApplication2.Product]]'.

Ответы [ 2 ]

1 голос
/ 19 марта 2012

Аргумент общего типа неверен для метода Ignore. Измените свой код на это:

var paramEx = Expression.Parameter(entityType);
var prop = Expression.Property(paramEx, "QuantityInStock");
var lambdaEx = Expression.Lambda(prop, paramEx);
var ignore = config.GetType().GetMethod("Ignore").MakeGenericMethod(prop.Type);

РЕДАКТИРОВАТЬ: вызов HasColumnName:

var property = config.GetType().GetMethod("Property", new Type[] { lambdaEx.GetType() });
var hasColumnName = property.ReturnType.GetMethod("HasColumnName");

hasColumnName.Invoke(
    property.Invoke(config, new[] { lambdaEx }),
    new[] { "UnitsInStock" });

Однако это не работает для структур, исключенных из списка перегрузки, таких как long или аналогичных, значение property будет null в этих случаях. Следовательно, вам придется искать общий метод Property с помощью GetMethods и выбрать подходящий (с или без типа Nullable<T> в параметре Expression).

0 голосов
/ 19 марта 2012

IMO это не целевое назначение Fluent API.Задача Fluent API состоит в том, чтобы предоставить более удобный для чтения и простой способ настройки, обеспечивая при этом безопасность времени компиляции.Я не вижу ничего подобного в этом подходе.

Лучшим способом экстернализации конфигурации является использование класса EntityTypeConfiguration и добавление их в ModelBuilder.

...