简体   繁体   中英

How to translate LINQ string.Contains(“substring%”) correctly for nHibernate?

The following code is used to give nHibernate a way to translate my C# LINQ code to proper SQL-statements. What I want is to have 3 SQL-statements like:

"Select * From HITable Where Series LIKE %substring"

or

"Select * From HITable Where Series LIKE substring%"

or

"Select * From HITable Where Series LIKE sub%ng"

The problem is that when nHibernate gets this it translates StartsWith, EndsWith, and Contains in all 3 cases to %substring%, ie wildcard is put both in the beginning and in the end of the substring. What is the proper way solve this?

    private static Expression<Func<HIProduct, bool>> CheckWildCardPosition(string rangeFrom)
    {
        if (rangeFrom.StartsWith(SqlWildCardAnyValue.ToString()))
        {
            return hip => hip.ProductId.Series.StartsWith(rangeFrom);
        }
        else if (rangeFrom.EndsWith(SqlWildCardAnyValue.ToString()))
        {
            return hip => hip.ProductId.Series.EndsWith(rangeFrom);
        }
        else
        {
            return hip => hip.ProductId.Series.Contains(rangeFrom);
        }
    }

I discovered that the problem when using StartsWith/EndsWith is that you have to remove the '%'-character, otherwise you actually will get 2 '%'-characters. This is because nHibernate translates StartsWith/EndsWith to a '%'. So, a first draft of the solution in code would look like the following:

    private static Expression<Func<HIProduct, bool>> CheckWildCardPosition(string serie)
    {
        char[] wildCard = new char[] { SqlWildCardAnyValue };

        if (serie.StartsWith(SqlWildCardAnyValue.ToString()))
        {
            if (serie.EndsWith(SqlWildCardAnyValue.ToString()))
            {
                return hip => hip.ProductId.Series.Contains(serie.Trim(wildCard));
            }
            return hip => hip.ProductId.Series.EndsWith(serie.TrimStart(wildCard));
        }
        else if (serie.EndsWith(SqlWildCardAnyValue.ToString()))
        {
            return hip => hip.ProductId.Series.StartsWith(serie.TrimEnd(wildCard));
        }
        else
        {
            string[] split = serie.Split(wildCard);
            return hip => hip.ProductId.Series.StartsWith(split[0]) && hip.ProductId.Series.EndsWith(split[1]);
        }
    }

Remember that this is a first draft, and I know the code could be refactored to more effective code, but in a first step this solves my problem.

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