Свободные подклассы - только первые и последние записи преобразуются в правильные типы - PullRequest
0 голосов
/ 28 мая 2011

У меня очень странная проблема, которую я не могу объяснить. У меня есть базовое отображение с этим

//This will automatically cast the row into the correct object type based on the value in AccountType
DiscriminateSubClassesOnColumn<string>("AccountType")
            .Formula(String.Format("CASE AccountType WHEN {0} THEN '{1}' WHEN {2} THEN '{3}' ELSE '{4}' END", 
            (int)PaymentMethodType.CheckingAccount, 
            typeof(ACH).Name,
            (int)PaymentMethodType.SavingsAccount,
            typeof(ACH).Name,
            typeof(CreditCard).Name));

Я посмотрел в журналах, я выполнил sql, который генерирует nhibernate, и все записи имеют одинаковые данные. В них нет разницы, которая бы обозначала, почему это не должно работать.

Базовый класс - PaymentMethodBase. У меня есть 2 подкласса, CreditCard и ACH, которые наследуются от PaymentMethodBase.

Тогда у меня есть это расширение

public static string PaymentMethodName(this PaymentMethodBase paymentMethod)
{
        if (paymentMethod is ACH)
        {
            var ach = (ACH)paymentMethod;
            return String.Format("{0} {1}", ach.BankName, String.Format("XXXX{0}", ach.AccountNumber.Substring(ach.AccountNumber.Length - 4)));
        }

        if (paymentMethod is CreditCard)
        {
            var creditCard = (CreditCard)paymentMethod;
            return String.Format("{0} {1}", creditCard.Name, creditCard.CreditCardNumber);
        }

        return "Unknown Payment Method";
    }

Который я так называю.

public SelectList PaymentMethodsSelectList
{
    get
    {
        var methods = (from p in PaymentMethods
                       where p != null
                       select new
                       {
                           id = p.PaymentMethodId,
                           name = p.PaymentMethodName()
                       }).OrderBy(x => x.name);

        var results = methods.ToList();

        results.Insert(0, new { id = (int)NewPaymentMethods.ACH, name = "<New eCheck Account...>" });
        results.Insert(0, new { id = (int)NewPaymentMethods.CreditCard, name = "<New Credit Card...>" });

        return new SelectList(results, "id", "name");
    }
}

Этот код используется 2 моделями. Все способы оплаты поступают из одного и того же объекта - объекта клиента. Коллекция отображается следующим образом.

HasMany<PaymentMethodBase>(x => x.PaymentMethods)
    .KeyColumn("CustomerId")
    .Where(y => y.AccountType < 10)
    .Inverse()
    .Cascade.All();

Итак, я получаю клиента двумя разными способами. Во-первых, я получаю клиента через другой объект (основной сайт). У другого есть объект, который тянет непосредственно по id (в iframe). Метод direct by id работает каждый раз. Другой метод, при котором я получаю клиента через другой объект, приводит к правильному приведению только первого и последнего метода оплаты. Если их больше 2, они остаются в базовом классе и появляются в середине списка после сортировки.

Я попытался изменить родительский объект, чтобы просто сопоставить идентификатор, а затем получить запись клиента по идентификатору. Провал. На этом пути есть что-то еще, но только на этой модели.

Ответы [ 2 ]

1 голос
/ 28 мая 2011

Я подозреваю, что проблема заключается в проблеме извлечения.

Поскольку метод расширения работает на стороне .Net, а не на «уровне NHibernate», он не может работать должным образом, когда набор методов оплаты недоступен.

Возможно, в методах direct by Id у вас настроено извлечение для платежей, тогда как в косвенном методе автоматическое извлечение идет только к объекту Customer, но останавливается на короткое время перед извлечением методов Payment.

Попробуйте дать NHibernate предварительную выборку способов оплаты для вас косвенным методом.

Что-то вроде:

Session.Query<SomeObject>.Where(.....).Fetch(x => x.Customer).ThenFetch(c => c.PaymentMethods)
0 голосов
/ 06 июня 2011

Проблема здесь заключалась в использовании методов расширения в операторе linq для возврата значения, основанного на типе. Проблема в том, что в некоторых местах он будет работать, но не в других, возможно, из-за какой-то проблемы с извлечением, как это было предложено Variant.

Я решил эту проблему, сделав свойство в базовом классе следующим образом:

public virtual string DisplayName { get { return "Unknown"; } }

Затем я переопределил свойство в своем дочернем классе и добавил логику, которая была в методе расширения для этого типа.

public override string DisplayName { get { return String.Format("{0} {1}", Name, AccountMask); } }
...