Вы можете использовать Properties
метод DbModelBuilder
. Перевести паскаль шаблон, чтобы подчеркнуть рисунок легко, как это:
modelBuilder.Properties()
.Configure(e => e.HasColumnName(Regex.Replace(e.ClrPropertyInfo.Name, "(?<=.)(?=[A-Z])", "_").ToUpper());
Шаблон также может быть, как это (.)([A-Z])
и замена должна быть затем $1_$2
.
Конечно, имя ввода должно иметь форму SomeThing
. Вы также можете взять шаблон в Dapper (опубликованный в вашем вопросе), который более точно работает в некоторых других редких случаях (даже в том числе и в этом формате DDos
(который будет преобразован в D_Dos
). Дело здесь не в переводе в верхний регистр для вы
Edit:.
жаль, что в EF5, MODELBUILDER не Properties()
метод Таким образом, для конкретного типа сущности, вы можете попробовать это:.
//in your OnModelCreating scope
//names of navigation properties defined in Job should be passed
//in TransformAllColumns method
new CapsUnderscorePropertiesConfig<Job>(modelBuilder).TransformAllColumns();
//a helper class
public class CapsUnderscorePropertiesConfig<T> where T : class
{
EntityTypeConfiguration<T> _entityConfig;
Dictionary<Type, MethodInfo> _propertyMethods = new Dictionary<Type,MethodInfo>();
MethodInfo propertyForStruct;
MethodInfo propertyForNullableStruct;
public CapsUnderscorePropertiesConfig(DbModelBuilder modelBuilder)
{
_entityConfig = modelBuilder.Entity<T>();
}
void config(PropertyInfo pInfo)
{
var p = Expression.Parameter(typeof(T));
var expType = typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(typeof(T), pInfo.PropertyType));
MethodInfo mi;
_propertyMethods.TryGetValue(pInfo.PropertyType, out mi);
if (mi == null)
{
if (pInfo.PropertyType.IsValueType)
{
//find the Property method for struct type having argument matching Expression<Func<TEntityType, T?>>
//note the T? inside Func<...> (there is another overload but with T instead).
if (propertyForStruct == null)
{
foreach(var prop in _entityConfig.GetType().GetMethods().Where(m => m.Name == "Property" && m.IsGenericMethodDefinition)
.Select(e => new { genMethodDef = e, genMethod = e.MakeGenericMethod(pInfo.PropertyType) })){
//there should be just 2 generic Property<T> methods filtered inhere.
//One is for nullable struct and the other is for struct.
var secondFuncArgType = prop.genMethodDef.GetParameters()[0].ParameterType.GetGenericArguments()[0].GetGenericArguments()[1];
if (secondFuncArgType.IsGenericType && secondFuncArgType.GetGenericTypeDefinition() == typeof(Nullable<>))
propertyForNullableStruct = prop.genMethodDef;
else propertyForStruct = prop.genMethodDef;
}
}
mi = pInfo.PropertyType.IsGenericType && pInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ?
propertyForNullableStruct.MakeGenericMethod(pInfo.PropertyType) :
propertyForStruct.MakeGenericMethod(pInfo.PropertyType);
}
else //possible property type is string, byte[] or geo type
{
mi = _entityConfig.GetType().GetMethods().Single(m => m.Name == "Property" && !m.IsGenericMethodDefinition
&& m.GetParameters()[0].ParameterType == expType);
}
_propertyMethods[pInfo.PropertyType] = mi;
}
var propConfig = mi.Invoke(_entityConfig, new object[] { Expression.Lambda(Expression.Property(p, pInfo.Name), p) }) as PrimitivePropertyConfiguration;
propConfig.HasColumnName(Regex.Replace(pInfo.Name, "(?<=.)(?=[A-Z])", "_").ToUpper());
}
//at the time of configuring, the Metadataworkspace is not present
//So we cannot know which properties are navigation properties
//Those propertie can be excluded by passing their names in here
public void TransformAllColumns(params string[] excludedNavProperties)
{
foreach (var prop in typeof(T).GetProperties().Where(p => !excludedNavProperties.Contains(p.Name)))
{
config(prop);
}
}
}
N OTE: Приведенный выше код работает только для прямых свойств, если у вас есть некоторые сложные свойства (возвращающий ComplexType
), тогда это не сработает. Технически вам нужно исключить все свойства (возвращающие ComplexType) из свойств объекта, а затем, если возможно, объединить свойства ComplexType
с прямыми свойствами объекта, прежде чем перебирать все и настраивать каждый.
PS: Я не уверен, если Dapper.FluentMap поддерживает EF5, но из кода вы в курсе, это может быть столь же легко, как прилагая ToUpper()
метод, как это:
public PropertyTransformConvention()
{
Properties()
.Configure(c => c.Transform(s => Regex.Replace(input: s, pattern: "([A-Z])([A-Z][a-z])|([a-z0-9])([A-Z])", replacement: "$1$3_$2$4").ToUpper()));
}
Я пробовал посетить домашнюю страницу Dapper.FluentMap и выглядит так, что у него есть классы на основе Convention
(если это от EF, он поддерживается только с EF6).Поэтому я не уверен, работает ли код Dapper в EF5. Если это работает, вы должны попробовать код выше для удобства.
Выглядит отлично, но modelBuilder не имеет метода Properties(). Я обновил вопрос, чтобы указать, как я попытался использовать ваш ответ, но синтаксис неверен. – McArthey
Что касается вашего редактирования, это именно то, что у меня есть в вопросе. Проблема в том, что e.HasColumnName выдает ошибку, потому что это не метод типа Job. – McArthey
@McArthey извините, похоже, что с EF5 работать нелегко. Технически вам нужно использовать Reflection для циклического переключения всех свойств объекта (за исключением навигационных свойств), а затем выбрать правильный метод 'Property' (который довольно сложный) 'EntityTypeConfiguration', тогда вам нужно создать' Expression' (как аргумент для 'Property') вручную из свойства Type и его Name ... Это совсем не просто. Может быть, есть и другой подход. Позвольте мне попытаться выяснить или бороться с этим. Даже когда я это сделаю, я уведомит вас, чтобы попробовать (не уверен, что он может работать). – Hopeless