映射和查询用户类型 - DB 中可为空到域中不可为空

发布于 2024-10-17 17:18:55 字数 2070 浏览 0 评论 0原文

我有一个遗留应用程序,在数据库中具有可为空的 DateTime 列 - NULL 值用于表示 +Infinity。我的应用程序使用相当标准的 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并返回(以及实际的日期时间),但我还没有发现如何让查询像我想要的那样编​​写。也就是说,现在,上面的 Linq 和我的代码将生成查询:

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

有人对在哪里查找或有类​​似的工作示例有任何建议吗? 我似乎找不到正确的集合关键字来找到与我认为已解决的问题相匹配的内容。这纯粹是一个需要解决的 NH 问题,还是还涉及 Linq2NH 的一些工作?

I have a legacy app with a nullable DateTime column in the database -- a NULL value is used to represent +Infinity. My app uses a fairly standard NHibernate + DDD setup, including Fluent-NHibernate and Linq2NHib.

Let's assume I have the following C# class that represents an entity.

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

It turns out there are rules governing this ExpirationDate that I want to encapsulate, for instance, it must be at midnight and can have the value of Infinity. In the legacy app NULL == Infinity just like in the DB. I want to convert it to something more like this set of classes:

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...
}

I do not currently have the option to convert all existing NULLs in the DB to a constant, but I would love to query inside my domain with something like this...

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

...and have NH know to translate into this...

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

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

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

I've been taking a look at User Types in NH and have made an IUserType to convert from Infinity to NULL and back (along with actual DateTime), but I haven't discovered how to get the query to be written like I want. That is, right now, the above Linq and my code would produce the query:

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

Does anyone have any suggestions on where to look or have a similarly working example? I can't seem to find the right set of keywords to find a match to something I assume is a solved problem. Is this purely a NH problem to solve, or will this also involve some work with Linq2NH?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遥远的她 2024-10-24 17:18:55

我的方法是为 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();

The way I would do it is map a protected property for the ExpirationDate and then expose a public readonly property for the OpenBusinessDate like so:

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;}
}

And then override the mapping of the discount class like so:

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

then in your linq query you'll be able to apply the infinity logic yourself like so

 return (from d in session.Linq<Discount>
           where d.ExpirationDate > expiringAfterDate || d.ExpirationDate != null
           select d).ToList();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文