Fluent NHibernate не успява да картографира автоматично свойства, генерирани от база данни от родителски клас

Имам вече съществуваща база данни, с която се опитвам да използвам автоматичното картографиране на Fluent NHibernate. Много от таблиците имат колони за одит, така че това, което реших, че би било разумно, е много от обектите да наследят прост абстрактен клас като този:

public abstract class AuditableEntity
{
    public virtual string   CreatedBy { get; set; }
    public virtual DateTime CreatedOn { get; set; }
    public virtual string   ModifiedBy { get; set; }
    public virtual DateTime ModifiedOn { get; set; }
}

Проблемът възниква, защото тези стойности са зададени в базата данни и ако се опитам да вмъкна нов обект без да задам тези стойности, получавам SqlTypeException : SqlDateTime overflow, тъй като като тип стойност, DateTime се инициализира на DateTime.MinValue.

Това, което се опитах да направя, за да поправя това, беше да добавя замяна на автоматично картографиране като това:

public class AuditableEntityOverride : IAutoMappingOverride<AuditableEntity>
{
    public void Override(AutoMapping<AuditableEntity> mapping)
    {
        mapping.Map(x => x.CreatedBy).Generated.Insert();
        mapping.Map(x => x.CreatedOn).Generated.Insert();
        mapping.Map(x => x.ModifiedBy).Generated.Always();
        mapping.Map(x => x.ModifiedOn).Generated.Always();
    }
}

Това обаче всъщност не прави нищо!

Мога да поправя проблема, като изрично отменя съпоставянето за всеки обект, който наследява колоните за проверка, но това са доста обекти и се опитвам да оставя Fluent NHibernate да свърши по-голямата част от работата тук.

Има ли нещо, което мога да направя, за да наложа това картографиране върху всички подкласове?

Актуализация

В случай, че помогне, ето как създавам фабриката за сесии. Може би има нещо, което пропускам и тук:

var sessionFactory = Fluently.Configure(new Configuration().AddProperties(new Dictionary<string, string>
{
    {Environment.ConnectionDriver,typeof (SqlClientDriver).FullName},
    {Environment.Dialect,typeof (MsSql2008Dialect).FullName},
    {Environment.ConnectionProvider,typeof (DriverConnectionProvider).FullName},
    {Environment.ConnectionString, connectionString},
    {Environment.ShowSql, "true"},
    {Environment.BatchSize, "100"},
    {Environment.Isolation,"ReadCommitted"}
}))
.Mappings(map => map.AutoMappings.Add(AutoMap.AssemblyOf<Transaction>(new AutomappingConfiguration())
                                            .Conventions.AddFromAssemblyOf<ReferenceConvention>()
                                            .Conventions.Add(DynamicUpdate.AlwaysTrue())
                                            .Conventions.Add(DynamicInsert.AlwaysTrue())
                                            .UseOverridesFromAssemblyOf<CurrencyOverride>))
.BuildSessionFactory();

person adhocgeek    schedule 10.10.2013    source източник
comment
Може би можете да използвате nullable DateTime? Или можете да създадете Interceptor, за да попълните необходимите полета   -  person Alex    schedule 10.10.2013
comment
Задаването на свойствата като nullable заобикаля проблема, да, но това не е истинско представяне на db схемата. Db е тази, която попълва полетата, така че не искам да правя нищо в C#, за да ги променя.   -  person adhocgeek    schedule 10.10.2013


Отговори (1)


Всъщност трябва да можете да напишете своя собствена конвенция, като внедрите интерфейса IPropertyConvention и проверите имената на екземплярите, например:

public class DefaultAutiableConvention: IPropertyConvention
{
    public void Apply(IPropertyInstance instance)
    {
        if (instance.Name == "CreatedBy" || instance.Name == "CreatedOn")
        {
            instance.Generated.Insert();
        }
        else if (instance.Name == "ModifiedBy" || instance.Name == "ModifiedOn")
        {
            instance.Generated.Always();
        }
    }
}

И след това добавете тази конвенция също към вашата конфигурация

.Conventions.Add(new DefaultAutiableConvention())
person MichaC    schedule 12.10.2013