Свободное наследование автомата NHibernate с подклассом - PullRequest
2 голосов
/ 23 марта 2011

У меня возникла проблема с использованием Fluent NHibernate с автоматическим наследованием. Ниже моя установка сущности (сокращенно для простоты). Я настроил Fluent NHibernate для создания 1 класса для иерархии со столбцом дискриминатора. Похоже, что автоматическое отображение работает правильно, так как при создании базы данных создается одна таблица с именем «AddressBase» со столбцом дискриминатора, который указывает тип адреса каждой строки.

Проблема заключается в том, что когда я вызываю метод "GetPrimaryBillingAddress ()" в классе UserAccount, вместо того, чтобы просто запрашивать адреса выставления счетов, NHibernate создает запрос, который проверяет адреса выставления счетов и доставки. Это вообще не учитывает дискриминатор. Я предполагаю, что есть какая-то конфигурация, которую я могу установить, но не смог ничего найти.

public abstract class AddressBase : ActiveRecord<AddressBase>
{
    public virtual long Id { get; set; }

    public virtual string Address1 { get; set; }

}

public class AddressBilling : AddressBase
{
    public class TypedQuery : ActiveRecordQuery<AddressBilling> { }

    public virtual bool IsPrimary { get; set; }
}

public class AddressShipping : AddressBase
{
    public class TypedQuery : ActiveRecordQuery<AddressShipping> { }

    [Display(Name = "Is Primary")]
    public virtual bool IsPrimary { get; set; }

}

public class UserAccount : ActiveRecord<UserAccount>
{
    public virtual long Id { get; set; }

    public virtual IList<AddressBilling> BillingAddresses { get; set; }
    public virtual IList<AddressShipping> ShippingAddresses { get; set; }

    public UserAccount()
    {
        BillingAddresses = new List<AddressBilling>();
        ShippingAddresses = new List<AddressShipping>();
    }

    public virtual AddressBilling GetPrimaryBillingAddress()
    {
        if (BillingAddresses.Any(x => x.IsPrimary))
        {
            return BillingAddresses.Single(x => x.IsPrimary);
        }

        return BillingAddresses.FirstOrDefault();
    }

    public virtual AddressShipping GetPrimaryShippingAddress()
    {
        if (ShippingAddresses.Any(x => x.IsPrimary)) {
            return ShippingAddresses.Single(x => x.IsPrimary);            
        }

        return ShippingAddresses.FirstOrDefault();
    }

}

UPDATE: Вот функции переопределения Mapping, используемые в autopping:

private static FluentConfiguration GetFluentConfiguration(string connectionStringName = "CS")
{
        var autoMapping = AutoMap
            .AssemblyOf<Product>(new Mapping.AutoMappingConfiguration())
            .Conventions.Setup(c =>
            {
                c.Add<Mapping.ForeignKeyConvention>();
                c.Add<Mapping.DiscriminatorConvention>();
            })
            .IgnoreBase<AddressBilling.TypedQuery>()
            .IgnoreBase<AddressShipping.TypedQuery>()
            .IncludeBase<AddressBase>();

        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2005.ConnectionString(c => c.FromConnectionStringWithKey(connectionStringName)))
            .Mappings(m => m.AutoMappings.Add(autoMapping));
}

public class AutoMappingConfiguration : DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        var isStatic = type.IsAbstract && type.IsSealed;

        return type.Namespace == typeof(Entities.Product).Namespace && !isStatic;
    }

    public override bool IsDiscriminated(Type type)
    {

        if (type == (typeof(Entities.AddressBase))) {
            return true;
        }

        return false;
    }

    public override string GetDiscriminatorColumn(Type type)
    {
        return "Type";
    }

public class DiscriminatorConvention : ISubclassConvention
{
    public void Apply(ISubclassInstance instance)
    {
        //Address 
        if (instance.Name == typeof(AddressBilling).AssemblyQualifiedName)
        {
            instance.DiscriminatorValue(Enums.AddressType.BillingAddress);
        } 
        else if (instance.Name == typeof(AddressShipping).AssemblyQualifiedName)
        {
            instance.DiscriminatorValue(Enums.AddressType.ShippingAddress);
        }
    }
}

Спасибо!

1 Ответ

2 голосов
/ 23 марта 2011

Пожалуйста, попробуйте изменить свой класс UserAccount следующим образом:

public class UserAccount : ActiveRecord<UserAccount>
{
    public virtual IList<AddressBase> Addresses { get; set; }
    public virtual IList<AddressBilling> BillingAddresses { get {return this.Addresses.OfType<AddressBilling>();} }
    public virtual IList<AddressShipping> ShippingAddresses { get {return this.Addresses.OfType<AddressShipping>();} }
    // ...
}

Конечно, здесь должно отображаться только свойство Addresses.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...