简体   繁体   English

流利的NHibernate无法自动映射父类的数据库生成的属性

[英]Fluent NHibernate failing to automap database generated properties from parent class

I have a pre-existing database which I'm trying to use Fluent NHibernate automapping with. 我有一个现有数据库,正在尝试使用Fluent NHibernate自动映射。 Many of the tables have audit columns, so what I thought would be reasonable is for many of the entities to inherit a simple abstract class like this : 许多表都有审计列,所以我认为合理的是许多实体都可以像这样继承一个简单的抽象类:

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; }
}

The problem arises because these values are set in the database, and if I try to insert a new entity without setting these values I get a SqlTypeException : SqlDateTime overflow because, being a value type, DateTime is initialised to DateTime.MinValue . 出现问题是因为这些值是在数据库中设置的,并且如果我尝试插入新实体而不设置这些值, SqlTypeException : SqlDateTime overflow因为作为值类型, DateTime被初始化为DateTime.MinValue

What I tried to do to fix this was add an automapping override like this : 我试图解决此问题的方法是添加一个自动映射覆盖,如下所示:

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();
    }
}

However, this doesn't actually do anything! 但是,这实际上没有任何作用!

I can fix the problem by explicitly overriding the mapping for each entity which inherits the audit columns, but that is quite a lot of entities and I'm trying to let Fluent NHibernate do most of the work here. 我可以通过显式覆盖继承审核列的每个实体的映射来解决此问题,但这是很多实体,我正在尝试让Fluent NHibernate在这里完成大部分工作。

Is there something I can do to enforce this mapping upon all subclasses? 我可以做些什么来在所有子类上强制执行此映射吗?

Update 更新

In case it helps, this is how I'm creating the session factory. 如果有帮助,这就是我创建会话工厂的方式。 Maybe there's something I'm missing here as well : 也许这里也缺少我一些东西:

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();

You should actually be able to write your own convention by implementing the IPropertyConvention interface and checking against the instance names, for example: 实际上,您应该能够通过实现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();
        }
    }
}

And then add that convention also to your configuration 然后将该约定也添加到您的配置中

.Conventions.Add(new DefaultAutiableConvention())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM