在Nhibernate中使用本地SQL Server函数

本文关键字:SQL Server 函数 Nhibernate | 更新日期: 2023-09-27 18:04:08

我正在构建一个通过Nhibernate查询数据库的WPF应用程序。

我有一个SQL Server数据库的表xuser,其中有一个标志(xflag),存储用户的权限。

现在我有这个SQL查询来提取超级用户或管理员:
select * 
from xuser 
where (CONVERT(int,xflag) & 2 > 0 ) or (CONVERT(int,xflag) & 1 > 0 ) 

其中2 = flag_administrators1 = flag_superusers

如果没有SQL函数CONVERT,这个查询不能工作,错误:

'&'操作符中的数据类型numeric和int不兼容。

现在在我的WPF c# hibernate应用程序中,我使用:

var xadmins= session.Query<Xuser>()
                    .Where(p => (p.Xflag & (int)Flag.FLAG_SUPERUSER)>0).ToList<string>();

这个查询不能处理相同的SQL错误。

我想在这个Linq2Nhibernate查询中使用T-SQL函数。我该怎么做呢?

最大的问题是这个应用程序必须使用MsSql2008Oracle方言。如果我在这里使用Convert函数,当我将db更改为Oracle时,这个函数会出错。什么是最佳实践?

在Nhibernate中使用本地SQL Server函数

您可以将xflag的映射指定为公式,以便将其转换为int,即

<property name="Xflag" formula="CONVERT(int,xflag)"/>

或for Fluent NHibernate

Map(x => x.Xflag).Formula("CONVERT(int,xflag)");

然后你可以使用你的表达式来获得所有的超级用户,而不需要强制转换:

var xadmins= session.Query<Xuser>()
                .Where(p => (p.Xflag & Flag.FLAG_SUPERUSER)>0).ToList<string>();

当然,这是SQL Server特有的缺点。为了在Oracle中工作,您需要使用映射:

<property name="Xflag" formula="to_number(xflag)"/>

为了解决这个问题,我们可以在两个db中创建一个用户定义函数来执行转换,这样映射就会变成:

<property name="Xflag" formula="xflag_conversion(xflag)"/>

Oracle UDF如下所示

CREATE FUNCTION xflag_conversion(xflag IN CHAR) 
  RETURN NUMBER 
   BEGIN  
  RETURN(to_number(xflag)); 
END;

SQL Server UDF应该是:

CREATE FUNCTION xflag_conversion (@xflag CHAR)
  RETURNS INT
  AS
  BEGIN
    RETURN CONVERT(int,xflag)
  END

不能保证udf的准确性,因为我还没有测试过它们。

最后,这里有一个关于查询标志信息的相关问题,你可能会感兴趣:如何查询NHibernate中存储为enum的标志