Linq to Entities复杂动态搜索

时间:2011-10-13 15:08:21

标签: entity-framework dynamic linq-to-entities

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

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

是否可以使用LINQ实现这种功能,以便我们可以利用延迟加载机制?如果可能的话,我真的想避免生成SQL字符串。我查看了Dynamic LINQ with Expression Trees,但无法使其发挥作用(或this)。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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;
}

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