Отображение и запрос пользовательских типов - Обнуляемый в БД и не обнуляемый в Домене - PullRequest
0 голосов
/ 16 февраля 2011

У меня есть устаревшее приложение с обнуляемым столбцом DateTime в базе данных - для представления + Infinity используется значение NULL.Мое приложение использует довольно стандартную установку NHibernate + DDD, включая Fluent-NHibernate и Linq2NHib.

Давайте предположим, что у меня есть следующий класс C #, который представляет сущность.

class Discount
{
    DateTime? ExpirationDate { get; set; }
    // ... etc.
}

Оказывается, тамэто правила, управляющие этим ExpirationDate, которые я хочу инкапсулировать, например, он должен быть в полночь и может иметь значение Infinity.В устаревшем приложении NULL == Infinity так же, как в БД.Я хочу преобразовать его во что-то более похожее на этот набор классов:

class Discount
{
    OpenBusinessDate ExpirationDate { get; set; } // assume not nullable
}

class OpenBusinessDate // immutable
{
    private DateTime _Value;
    private bool _IsInfinity;

    OpenBusinessDate(DateTime? value)
    {
        if (null == value)
        {
            _IsInfinity = true;
            _Value = DateTime.MaxValue; // or SqlDateTime.MaxValue if you must
        }
        else
        {
            ErrorIfNotMidnight(value);
            _Value = value;
        }
    }

    DateTime ToDateTime() { return _Value; }

    // ... casters, comparison methods, etc...
}

В настоящее время у меня нет возможности преобразовать все существующие значения NULL в БД в константу, но я бы хотел выполнить запрос внутри моегодомен с чем-то вроде этого ...

IList<Discount> GetAll(OpenBusinessDate expiringAfterDate)
{
    return (from d in session.Linq<Discount>()
           where d.ExperationDate > expiringAfterDate
           select d).ToList();
}

... и NH знает, как перевести на это ...

SELECT * FROM Discount 
WHERE (ExpirationDate IS NULL 
    OR ExpirationDate > @expiringAfterDate)

/* ...or possibly this... */

SELECT * From Discount
WHERE (COALESCE(ExpirationDate, '9999-12-31') > @expiringAfterDate)

Я смотрел на типы пользователейв NH и сделал IUserType для преобразования из Infinity в NULL и обратно (вместе с фактическим DateTime), но я не обнаружил, как получить запрос, который будет написан так, как я хочу.То есть, прямо сейчас приведенный выше Linq и мой код вызовут запрос:

SELECT * FROM Discount
WHERE (ExpirationDate > 'Infinity')
/* b/c OpenBusinessDate.ToString() on Infinity 
   produces "Infinity" for debugging purposes */

У кого-нибудь есть предложения по поиску или схожим рабочим примером? Я не могу найти правильный набор ключевых слов, чтобы найти совпадение с чем-то, что, я полагаю, является решенной проблемой.Это просто проблема NH, которую нужно решить, или это также потребует работы с Linq2NH?

1 Ответ

1 голос
/ 16 февраля 2011

Я бы сделал это, сопоставив защищенное свойство для ExpirationDate, а затем выставив открытое свойство только для чтения для OpenBusinessDate следующим образом:

public class Discount
{
    private DateTime _value;
    protected DateTime? ExpirationDate 
    {
        get { return _value; }
        set { 
                _value = value; 
                ExpirationDate = new OpenBusinessDate(value); 
            }
    }
    public OpenBusinessDate OpenExpirationDate {get; private set;}
}

И затем переопределив сопоставление класса скидки следующим образом:

public PersonMap : ClassMap<Discount>
{  
    public PersonMap()  
    {  
        Map(Reveal.Property<Discount>("ExpirationDate ")) 
    }  
}

, тогда в своем запросе linq вы сможете самостоятельно применить логику бесконечности, например

 return (from d in session.Linq<Discount>
           where d.ExpirationDate > expiringAfterDate || d.ExpirationDate != null
           select d).ToList();
...