过滤逗号分隔的数据 [英] Filtering Comma Separated Data

查看:65
本文介绍了过滤逗号分隔的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的网站上有一堆小部件,我正在尝试根据传入的URL对其进行过滤.说一个小部件具有以下结构:

My site has a bunch of widgets and i'm trying to filter them based on the url which is passed in. Say a Widget has the following structure:

public class Widget {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Urls { get; set; }
}

其中Urls是用逗号分隔的列表,用于显示小部件的网址,例如:

Where Urls is a comma separated list for the urls where the widget should be displayed, e.g.:

/,/博客/,/博客/123,/新闻/*

/, /Blog/, /Blog/123, /News/*

新闻后面的星号表示只要传入的网址以/News/开头,就会选择该小部件.

The asterisk after News indicates the Widget will be selected whenever the passed in url starts with /News/.

如何根据我的上述条件修改以下方法以过滤窗口小部件?

How could i modify the following method to filter the widgets based on my conditions above?

public IList<Widget> GetWidgets(string url) {
    return _session
        .Where(w => w.Urls.Contains(url))
        .ToList();
}

理想情况下,我想使用linq查询,它只能访问数据库一次.非常感谢您的帮助.谢谢

Ideally i'd like to use a linq query and it must only hit the database once. I'd appreciate the help. Thanks

推荐答案

我通过添加自己的通配符匹配生成器设法解决了这个问题.参见 http://sentinel101.wordpress.com/2010/12/30/extend-nhibernate-linq-for-regex-matching/例如,如何注册生成器.如果有人感兴趣,这是生成器:

I managed to solve this by adding my own wild card match generator. See http://sentinel101.wordpress.com/2010/12/30/extend-nhibernate-linq-for-regex-matching/ for example of how to register the generator. Here's the generator incase anyone is interested:

public class WildCardMatchGenerator : BaseHqlGeneratorForMethod {
    public WildCardMatchGenerator() {
        var methodDefinition = ReflectionHelper.GetMethodDefinition(() => WildCardMatchExtensions.WildCardMatch(null, null, ','));
        SupportedMethods = new[] { methodDefinition };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) {
        return treeBuilder.Equality(treeBuilder.MethodCall("[dbo].[WildCardMatch]", new[] {
            visitor.Visit(arguments[0]).AsExpression(),
            visitor.Visit(arguments[1]).AsExpression(),
            visitor.Visit(arguments[2]).AsExpression()
        }), treeBuilder.Constant(1));
    }
}

这是WildCardMatch UDF:

And here is the WildCardMatch UDF:

CREATE FUNCTION [dbo].[WildCardMatch] (
    @Pattern NVARCHAR(MAX),
    @Input NVARCHAR(MAX),
    @Separator NVARCHAR(5)
)
RETURNS BIT
AS
BEGIN
    SET @Pattern = REPLACE(@Pattern, '*', '%')

    DECLARE @RtnValue BIT
    SELECT @RtnValue = CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM [dbo].[Split](@Pattern, @Separator) WHERE @Input LIKE [Data]

    RETURN @RtnValue
END

以及它调用的Split函数(来自 http://blogs.microsoft.co.il/blogs/itai/archive/2009/02/01/t-sql-split-function.aspx ):

And the Split function it calls (from http://blogs.microsoft.co.il/blogs/itai/archive/2009/02/01/t-sql-split-function.aspx):

CREATE FUNCTION [dbo].[Split]
(    
    @RowData NVARCHAR(MAX),
    @Separator NVARCHAR(MAX)
)
RETURNS @RtnValue TABLE 
(
    [Id] INT IDENTITY(1,1),
    [Data] NVARCHAR(MAX)
) 
AS
BEGIN 
    DECLARE @Iterator INT
    SET @Iterator = 1

    DECLARE @FoundIndex INT
    SET @FoundIndex = CHARINDEX(@Separator, @RowData)

    WHILE (@FoundIndex > 0)
    BEGIN
        INSERT INTO @RtnValue ([Data])
        SELECT Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))

        SET @RowData = SUBSTRING(@RowData, @FoundIndex + DATALENGTH(@Separator) / 2, LEN(@RowData))
        SET @Iterator = @Iterator + 1
        SET @FoundIndex = CHARINDEX(@Separator, @RowData)
    END

    INSERT INTO @RtnValue ([Data])
    SELECT Data = LTRIM(RTRIM(@RowData))

    RETURN
END

最后,您需要上述UDF的C#实现:

Lastly you'll need the C# implementation of the above UDF:

public static class WildCardMatchExtensions {
    public static bool WildCardMatch(this string pattern, string input, char separator = ',') {
        foreach (var str in pattern.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries)) {
            if (Regex.IsMatch(input, Regex.Escape(str.Trim()).Replace("\\*", ".*")))
                return true;
        }

        return false;
    }
}

希望这会有所帮助.

这篇关于过滤逗号分隔的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆