映射和查询用户类型 - DB 中可为空到域中不可为空
我有一个遗留应用程序,在数据库中具有可为空的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的方法是为 ExpirationDate 映射一个受保护的属性,然后为 OpenBusinessDate 公开一个公共只读属性,如下所示:
然后重写折扣类的映射,如下所示:
然后在 linq 查询中,您将能够像这样自己应用无穷逻辑
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:
And then override the mapping of the discount class like so:
then in your linq query you'll be able to apply the infinity logic yourself like so