简体   繁体   English

使用NHibernate函数通过QueryOver过滤结果

[英]Using NHibernate function to filter results with QueryOver

I am trying to use a SQL Function to filter results of a query. 我正在尝试使用SQL函数来过滤查询结果。 I have a function in SQL called SplitKeys that takes a csv string and returns a table of integers. 我在SQL中有一个名为SplitKeys的函数,该函数接受一个csv字符串并返回一个整数表。 I want to produce the following SQL (or close to it): 我想产生以下SQL(或接近它):

select * from Members where MemberKey in (select * from SplitKeys('1,2,3')) 从MemberKey所在的成员中选择*(从SplitKeys('1,2,3')中选择*)

I''m using QueryOver and can't seem to get something to produce that where clause. 我正在使用QueryOver,似乎无法获得产生该where子句的东西。 Since I couldn't get that to work, I created another function that took a string and id and returned the id if it was in the list, or -1 if not. 由于无法正常工作,因此我创建了另一个函数,该函数接受字符串和id,如果id在列表中,则返回id,否则返回-1。

session.QueryOver<Member>().Where(
    Restrictions.Ge(
        Projections.SqlFunction(
            "dbo.IsKeyInList",
            NHibernateUtil.StringClob,
            new[]
            {
                Projections.Constant(
                    keyList,
                    NHibernateUtil.StringClob),
                Projections.Constant(',', NHibernateUtil.Character),
                Projections.Property<Member>(x => x.MemberKey)
            }),
    0));

This works great, except it's slow. 这很有效,但速度很慢。 with the first query, the function is called once and it can then filter based on the table. 对于第一个查询,该函数被调用一次,然后可以根据该表进行过滤。 In the second it calls the function for every row. 在第二个中,它为每一行调用该函数。

I originally had this as a list of ints and passed that in. But, the problem with that is each element of the list is a parameter in the SQL and the max parameters is 2100. 我最初将其作为整数列表并将其传递给我。但是,问题在于列表中的每个元素都是SQL中的一个参数,最大参数为2100。

session.QueryOver().WhereRestrictionOn(x => x.MemberKey).IsInG(intKeyList); session.QueryOver()。WhereRestrictionOn(x => x.MemberKey).IsInG(intKeyList);

I've looked and looked and can't seem to find someone who has done that or get NHibernate and the C# compiler to like it. 我看了看又看,似乎找不到找到这样做的人或让NHibernate和C#编译器喜欢它的人。 I tried this and it doesn't work. 我试过了,它不起作用。 This and other variations either throw an exception with No Mapping for System.In32 or it returns nothing. 此变体或其他变体会抛出“ System.In32没有映射”的异常,或者不返回任何内容。

var keys =
    session.QueryOver<MemberKey>()
        .Select(
            Projections.SqlFunction(
                "dbo.SplitKeysCSV",
                NHibernateUtil.StringClob,
                new[] { 
                    Projections.Constant(keyList),
                    Projections.Constant(delimiter),
                }));

I tried creating some sort of mapping for the results, but I can't do that because there is no table. 我尝试为结果创建某种映射,但是由于没有表,所以无法执行此操作。 I tried using the .In() function, but that doesn't accept a Projects.SqlFunction. 我尝试使用.In()函数,但是不接受Projects.SqlFunction。

You can do this using a SqlCriterion: 您可以使用SqlCriterion做到这一点:

var sqlCrit = new SQLCriterion("{alias}.MemberKey in (SELECT * FROM dbo.SplitKeys(?))",
                new[]{ keyList }, new IType[]{ NHibernateUtil.String })
var keys = session.QueryOver<Member>()
            .Where(sqlCrit)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM