简体   繁体   中英

Using NHibernate function to filter results with QueryOver

I am trying to use a SQL Function to filter results of a query. I have a function in SQL called SplitKeys that takes a csv string and returns a table of integers. I want to produce the following SQL (or close to it):

select * from Members where MemberKey in (select * from SplitKeys('1,2,3'))

I''m using QueryOver and can't seem to get something to produce that where clause. 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.

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.

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

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.

You can do this using a 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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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