Как вы сопоставляете enum как значение int с белым NHibernate?
Вопрос говорит, что все действительно, по умолчанию для него нужно отображать как string
, но мне нужно отображать его как int
.
В настоящее время я использую PersistenceModel
для установки моих соглашений, если это имеет значение. Спасибо заранее.
Обновление
Установлено, что переход на последнюю версию кода из багажника разрешил мои проблемы.
Ответы
Ответ 1
Способ определения этого соглашения иногда менялся, теперь он:
public class EnumConvention : IUserTypeConvention
{
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => x.Property.PropertyType.IsEnum);
}
public void Apply(IPropertyInstance target)
{
target.CustomType(target.Property.PropertyType);
}
}
Ответ 2
Итак, как уже упоминалось, получение последней версии Fluent NHibernate с багажника привело меня туда, где я должен был быть. Пример отображения для перечисления с последним кодом:
Map(quote => quote.Status).CustomTypeIs(typeof(QuoteStatus));
Пользовательский тип заставляет его обрабатывать как экземпляр перечисления, а не использовать GenericEnumMapper<TEnum>
.
Я действительно рассматриваю возможность отправки патча, чтобы иметь возможность изменять между enum mapper, который продолжает строку, и тот, который сохраняется в int, поскольку это похоже на то, что вы можете установить как соглашение.
Это появилось в моей недавней деятельности, и все изменилось в более новых версиях Fluent NHibernate, чтобы сделать это проще.
Чтобы все перечисления отображались как целые числа, теперь вы можете создать такое соглашение:
public class EnumConvention : IUserTypeConvention
{
public bool Accept(IProperty target)
{
return target.PropertyType.IsEnum;
}
public void Apply(IProperty target)
{
target.CustomTypeIs(target.PropertyType);
}
public bool Accept(Type type)
{
return type.IsEnum;
}
}
Тогда ваше отображение должно быть:
Map(quote => quote.Status);
Вы добавляете соглашение к вашему Fluent NHibernate, например:
Fluently.Configure(nHibConfig)
.Mappings(mappingConfiguration =>
{
mappingConfiguration.FluentMappings
.ConventionDiscovery.AddFromAssemblyOf<EnumConvention>();
})
./* other configuration */
Ответ 3
Не забывайте об нулевых перечислениях (например, ExampleEnum? ExampleProperty
)! Их нужно проверять отдельно. Вот как это делается с новой конфигурацией стиля FNH:
public class EnumConvention : IUserTypeConvention
{
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => x.Property.PropertyType.IsEnum ||
(x.Property.PropertyType.IsGenericType &&
x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
);
}
public void Apply(IPropertyInstance target)
{
target.CustomType(target.Property.PropertyType);
}
}
Ответ 4
вот как я сопоставил свойство enum со значением int:
Map(x => x.Status).CustomType(typeof(Int32));
работает для меня!
Ответ 5
Для тех, кто использует Fluent NHibernate с Automapping (и потенциально контейнер IoC):
IUserTypeConvention
- это как @ Жюльен ответ выше: fooobar.com/questions/64287/...
public class EnumConvention : IUserTypeConvention
{
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => x.Property.PropertyType.IsEnum);
}
public void Apply(IPropertyInstance target)
{
target.CustomType(target.Property.PropertyType);
}
}
Конфигурация Fluent NHibernate Automapping может быть сконфигурирована следующим образом:
protected virtual ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(SetupDatabase)
.Mappings(mappingConfiguration =>
{
mappingConfiguration.AutoMappings
.Add(CreateAutomappings);
}
).BuildSessionFactory();
}
protected virtual IPersistenceConfigurer SetupDatabase()
{
return MsSqlConfiguration.MsSql2008.UseOuterJoin()
.ConnectionString(x =>
x.FromConnectionStringWithKey("AppDatabase")) // In Web.config
.ShowSql();
}
protected static AutoPersistenceModel CreateAutomappings()
{
return AutoMap.AssemblyOf<ClassInAnAssemblyToBeMapped>(
new EntityAutomapConfiguration())
.Conventions.Setup(c =>
{
// Other IUserTypeConvention classes here
c.Add<EnumConvention>();
});
}
* Тогда CreateSessionFactory
можно легко использовать в IoC, таком как Castle Windsor (используя PersistenceFacility и installer). *
Kernel.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(() => CreateSessionFactory()),
Component.For<ISession>()
.UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
.LifestylePerWebRequest()
);
Ответ 6
Вы можете создать NHibernate IUserType
и указать его с помощью CustomTypeIs<T>()
на карте свойств.
Ответ 7
Вы должны хранить значения как int/tinyint в таблице DB. Для отображения вашего перечисления вам нужно правильно указать отображение. См. Ниже пример отображения и перечисления,
Класс сопоставления
public class TransactionMap : ClassMap Transaction
{
public TransactionMap()
{
//Other mappings
.....
//Mapping for enum
Map(x => x.Status, "Status").CustomType();
Table("Transaction");
}
}
Enum
public enum TransactionStatus
{
Waiting = 1,
Processed = 2,
RolledBack = 3,
Blocked = 4,
Refunded = 5,
AlreadyProcessed = 6,
}