Linq to Entities 复杂动态搜索

发布于 2024-12-09 10:19:15 字数 616 浏览 0 评论 0原文

我们正在使用实体框架(MySQL 连接器),并在我们的 Web 应用程序上创建一个中央搜索工具。

此链接几乎正是我所需要的,除了他使用预定义的实体和属性这一事实。在我们的搜索场景中,我们将拥有动态数量的搜索词和字段(即:用户选择搜索姓氏、值和城市,或提供商和顾问)。

是否可以使用LINQ来实现这种功能,以便我们可以利用延迟加载机制?如果可能的话,我真的想避免生成 SQL 字符串。我查看了 带有表达式树的动态 LINQ 但无法无法让它工作(或这个)。

We're using the Entity Framework (MySQL connector) and are creating a central Search facility on our web application.

This link is almost exactly what I need, aside from the fact that he's using pre-defined entities and properties. In our search scenario, we'll have a dynamic number of search terms and fields (ie: user chooses to search on surname, value and city, or provider and advisor).

Is it possible to achieve this kind of functionality with LINQ, so that we can leverage the deferred loading mechanism? I really wanted to avoid generating SQL strings, if possible. I looked at Dynamic LINQ with Expression Trees but couldn't get this to work (or this).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

李白 2024-12-16 10:19:15

我知道您表示您希望避免生成 SQL 字符串,但这通常是最简单的方法。 (比自定义表达式树容易得多)。如果您在 EF 中执行此操作,我建议您查看 Entity Sql,它适用于您的概念模型,但允许比 LINQ 更多的动态查询选项。 LINQ确实适合编译时查询而不是运行时查询。您可以在 http://msdn.microsoft.com/en 阅读有关 Entity SQL 的内容-us/library/bb387145.aspx

I know you indicated that you wanted to avoid generating SQL strings, but that is often the easiest way. (Much easier than custom Expression Trees). If you are doing this in EF, I recommend you check out Entity Sql which works against your conceptual model but allows for more dynamic querying options than LINQ. LINQ is really suited to compile time query rather than run time queries. You can read up on Entity SQL at http://msdn.microsoft.com/en-us/library/bb387145.aspx.

黎夕旧梦 2024-12-16 10:19:15

自上周以来,我们面临着类似的问题,这是我刚刚想到的一个想法。我想我会和你分享的。

interface IPerson
{            
    DateTime BirthDay { get; set; }

    string City { get; set; }            

    string FirstName { get; set; }

    string LastName { get; set; }
}

interface IFilter { }

interface IPersonFilter : IFilter { }

class PersonFilter : IPersonFilter
{            
    public DateTime? BirthDay { get; set; }

    public string City { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }            
}

static IQueryable<TSource> ApplyFilter<TSource, TFilter>(IQueryable<TSource> source, TFilter filter) where TFilter : IFilter
{
    const BindingFlags bindingFlags = BindingFlags.Public|BindingFlags.Instance|BindingFlags.GetProperty;

    var retval = source;
    foreach (var filterProperty in filter.GetType().GetProperties(bindingFlags))
    {
        var elementParameter = Expression.Parameter(source.ElementType, "type");
        var elementProperty  = Expression.Property(elementParameter, filterProperty.Name);

        var value = filterProperty.GetGetMethod().Invoke(filter, null);
        if (value != null)
        {
            var constantValue = Expression.Constant(value, elementProperty.Type);
            var expression = Expression.Equal(elementProperty, constantValue);
            retval = retval.Where(Expression.Lambda<Func<TSource, bool>>(expression, elementParameter));
        }
    }

    return retval;
}

所以我们的想法是,您有一个过滤器,其中过滤器的属性名称与您要运行过滤器的对象的属性名称相匹配。如果属性的值不为空,我会为其构建一个表达式。为了简单起见,我仅构建 Expression.Equal 表达式,但我正在考虑扩展它。

since last week, we have a similar problem to face, here is an idea i just had for it. thought i share it with you.

interface IPerson
{            
    DateTime BirthDay { get; set; }

    string City { get; set; }            

    string FirstName { get; set; }

    string LastName { get; set; }
}

interface IFilter { }

interface IPersonFilter : IFilter { }

class PersonFilter : IPersonFilter
{            
    public DateTime? BirthDay { get; set; }

    public string City { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }            
}

static IQueryable<TSource> ApplyFilter<TSource, TFilter>(IQueryable<TSource> source, TFilter filter) where TFilter : IFilter
{
    const BindingFlags bindingFlags = BindingFlags.Public|BindingFlags.Instance|BindingFlags.GetProperty;

    var retval = source;
    foreach (var filterProperty in filter.GetType().GetProperties(bindingFlags))
    {
        var elementParameter = Expression.Parameter(source.ElementType, "type");
        var elementProperty  = Expression.Property(elementParameter, filterProperty.Name);

        var value = filterProperty.GetGetMethod().Invoke(filter, null);
        if (value != null)
        {
            var constantValue = Expression.Constant(value, elementProperty.Type);
            var expression = Expression.Equal(elementProperty, constantValue);
            retval = retval.Where(Expression.Lambda<Func<TSource, bool>>(expression, elementParameter));
        }
    }

    return retval;
}

so the idea is, that you have a filter where the names of the properties of filter match the property names of the object you want to run the filter against. and if the value of the property is not null, i build a expression for it. For the simplicity i do build Expression.Equal expressions only, but i am thinking about extending it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文