FluentNHibernate - Automapping ignore property

2019-04-02 02:53发布

问题:

I have a base class that contains a property called IsDirty. This is used for the domain model and is not a column in the database table.

When using automapping, fluent nhibernate tries to add this column to the table. A way to fix this is to put .ForTypesThatDeriveFrom<Address>(p => p.IgnoreProperty(x => x.IsDirty)) in the automapping setup.

The problem is, all my entities will do this, is there a way to state this without have to add this line for every entity? If I put .ForTypesThatDeriveFrom<Entity>(p => p.IgnoreProperty(x => x.IsDirty)), then I get an error trying to convert Entity to Address.

I also have entity set as the base type.

Thanks in advance, JT

回答1:

You create a class derived from DefaultAutomappingConfiguration and override the ShouldMap(Member member) method.

Like so:

public class AutoMapConfiguration : DefaultAutomappingConfiguration
{
    private static readonly IList<string> IgnoredMembers = new List<string> {"IsNew", "IsDeleted"};

    public override bool ShouldMap(Member member)
    {
        return base.ShouldMap(member) && !IgnoredMembers.Contains(member.Name);
    }
}

and then your fluent configuration will look something like:

Fluently.Configure()
    // Database settings
    .Mappings(m => {
        m.AutoMappings.Add(yourMappingAssembly, new AutoMapConfiguration())
    });


回答2:

I've had the same problem, except that NHibernate complained about a missing class.

I believe you can use the following convention to remove the part that maps the property from the class:

public class IgnorePropertiesClassMapConvention : IClassConvention
{
    public bool Accept(IClassMap classMaps)
    {
        return true;
    }
    public void Apply(IClassMap classMap)
    {
        var partsToIgnore = classMap.Parts.OfType<IProperty>()
            .Where(IgnoreProperty).ToList();

        foreach (var part in partsToIgnore)
            ((IList<IMappingPart>)classMap.Parts).Remove(part);

    }

    private bool IgnoreProperty(IProperty property)
    {
        // Your logic would be here
    }
}

The code I've used is a bit different, since what I needed to remove was a ManyToOne mapping:

public class IgnorePartsBasedOnReturnTypeClassMapConvention : IClassConvention
{
    public bool Accept(IClassMap classMaps)
    {
        return true;
    }
    public void Apply(IClassMap classMap)
    {
        var partsToIgnore = classMap.Parts.OfType<IManyToOnePart>()
            .Where(IgnorePart).ToList();

        foreach (var part in partsToIgnore)
            ((IList<IMappingPart>)classMap.Parts).Remove(part);

    }
    private bool IgnorePart(IManyToOnePart part)
    {
        return IgnoreProperty(part.Property);
    }

    private bool IgnoreProperty(PropertyInfo propertyInfo)
    {
        var ignoredNamespaces = new []{"namespacesToIgnore"};
        return ignoredNamespaces.Any(namespc => propertyInfo.GetGetMethod().ReturnType.Namespace.StartsWith(namespc));
    }
}

I'm not exactly sure if this is the best way to do this. My feeling is that the discoverability part should be overriden with the ability to not even build up the part for unwanted properties, but for now this seems to work.