4

I have an IAuditable interface that defines my class domain as auditable.

public interface IAuditable
{
    DateTime CreateAt { get; }
    IUser CreateBy { get; }
    DateTime? UpdateAt { get; }
    IUser UpdateBy { get; }
}

For these classes (there are many) that implement this interface, the configuration is the same! So I decided to override convention:

public class AudityConvention : IAutoMappingOverride<IAuditable>
{
    public void Override(AutoMapping<IAuditable> mapping)
    {
        mapping.Map(p => p.CreateAt).ReadOnly().Access.Property().Not.Nullable().Not.Update().Default("getDate()").Generated.Insert();
        mapping.References<Usuario>(p => p.CreateBy).Not.Nullable().Not.Update();

        mapping.Map(p => p.UpdateAt).ReadOnly().Access.Property().Default("getDate()").Not.Insert().Generated.Always();
        mapping.References<Usuario>(p => p.UpdateBy).Nullable().Not.Insert();
    }
}

And configure it

    _configuration = Fluently.Configure() // All config from app.config
        .Mappings(m =>
        {
            m.AutoMappings.Add(
                AutoMap.AssemblyOf<Usuario>()
                .UseOverridesFromAssemblyOf<AudityConvention>()
                .Conventions.Setup(c => c.AddFromAssemblyOf<EnumConvention>())
            );

            m.FluentMappings
                .AddFromAssemblyOf<UsuarioMap>()
                .Conventions.AddFromAssemblyOf<EnumConvention>()
                                    ;
        })
        .BuildConfiguration();

SessionFactory = _configuration.BuildSessionFactory();

Session = SessionFactory.OpenSession();

var export = new SchemaExport(_configuration);
export.Drop(false, true); // drop and recreate the database (Just to make sure that the settings are being applied)
export.Execute(false, true, false); // Create de database 

With this app.config

    <appSettings>
    <add key="FluentAssertions.TestFramework" value="mstest"/>
</appSettings>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
        <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
        <property name="connection.connection_string_name">Data</property>
        <property name="show_sql">true</property>
    </session-factory>
</hibernate-configuration>

Exemple domain class:

public class Entidade : IAuditable
{
    public virtual int Id { get; protected set; }
    [StringLength(255)]
    public virtual string Nome { get; set; }

    // Implements IAuditable
    public virtual DateTime CreateAt { get; protected set; }
    public virtual IUser CreateBy { get; set; }
    public virtual DateTime? UpdateAt { get; protected set; }
    public virtual IUser UpdateBy { get; set; }
}

And map it:

public class EntidadeMap : ClassMap<Entidade>
{
    public EntidadeMap()
    {
        Id(p => p.Id);
        Map(p => p.Nome);

        Table("Entidades");
    }
}

Results:

enter image description here

Question

What am I doing wrong? How to create a convention for all classes that implement IAuditable settings are the same!

The part of the configuration below was added later. From what I read, overwrite support only by AutoMappings conventions.

m.AutoMappings.Add(
    AutoMap.AssemblyOf<Usuario>()
    .UseOverridesFromAssemblyOf<AudityConvention>()
    .Conventions.Setup(c => c.AddFromAssemblyOf<EnumConvention>())
);
ridermansb
  • 10,779
  • 24
  • 115
  • 226
  • This is definitely possible via NHibernate's ByCode mappings, but have no idea whether the Fluent's DSL supports it. author's take : http://fabiomaulo.blogspot.in/search/label/ConfORM – kalki May 29 '13 at 14:42
  • I'm faced with exactly this issue working on a legacy application. How did you resolve in the end? – Chris Pickford Apr 18 '17 at 09:24
  • @ChrisPickford it's to old. I don't remember – ridermansb Apr 18 '17 at 11:49

2 Answers2

0

I think you're out of luck. I don't believe overrides work on interfaces. You're better off doing something like this:

public class BaseAuditable : IAuditable
{
   ....
}

public class Entidade : BaseAuditable
{ ... }

You can use

  IAutoMappingOverride<BaseAuditable> instead of IAutoMappingOverride<IAuditable>

I hope I'm wrong but I tried to make it work so many times with interfaces with no luck.

rivarolle
  • 1,528
  • 11
  • 18
  • Hi @rivarolle, Base class is not an option for me. Could achieve this goal by implementing the `IPropertyConvention` for each property. – ridermansb May 28 '13 at 22:05
0

a possiblity

var overrideMethod = typeof(AutoPersistenceModel).GetMethod("Override");

foreach (var type in typeof(IAuditable).Assembly)
{
    if (typeof(IAuditable).IsAssignableFrom(type))
    {
        overrideMethod.MakeGenericMethod(type).Invoke(new Action<IAuditable>(MapAuditables));
    }
}
Firo
  • 30,626
  • 4
  • 55
  • 94