繁体   English   中英

实体框架搜索喜欢或平等

[英]Entity Framework Search Like or Equal

我正在使用EntityFrameworkCore并且我正在尝试根据搜索对象是否包含通配符来创建搜索“等于”或“喜欢”的简化实例。 这是我正在使用的基础

public class Person
{
    public string Name;
    public string MothersName;
    public string FathersName;

}

public class SearchPerson
{
    public string Name;
}

public class Program
{
    public void FindPerson(SearchPerson searchPerson)
    {
        if (!string.IsNullOrEmpty(searchPerson.Name))
        {
            if (searchPerson.Name.Contains("%"))
            {
                EFPersonObject.Where(m => EF.Functions.Like(m.Name, searchPerson.Name));
            }
            else
            {
                EFPersonObject.Where(m => m.Name == searchPerson.Name);
            }
        }
    }
}

如果我的SearchPerson类扩展到5或10或15个可能的搜索参数,则会有很多重复的代码。 我应该能够在扩展中实现一些反射并在这里使用Jim C的响应,获取并传递属性的名称并将其大部分简化为一行

public static class SearchExtension
{
        public static void FindLike<T>(this DbSet<T> model, PropertyInfo info, string searchValue) where T : class
    {
        if (!string.IsNullOrEmpty(searchValue))
        {
            if (searchValue.Contains("%"))
            {
                model.Where(m => EF.Functions.Like(typeof(T).GetProperty(info.Name).GetValue(model, null).ToString(), searchValue));
            }
            else
            {
                model.Where(m => typeof(T).GetProperty(info.Name).GetValue(model, null).ToString() == searchValue);
            }
        }
    }
}

用法:

EFPersonObject.FindLike(typeof(Person).GetProperty(RemoteMgr.GetPropertyName(()=>typeof(Person).Name)), searchPerson.Name);

(我还没有测试过它,但是如果它不对,它应该是接近的),但我会假设我会受到性能影响。 还有另一种方法可以实现这一点,在这种情况下不需要反射来避免性能损失吗?

在查询表达式树中使用反射(和其他非SQL可翻译)调用不是一个好主意。 在EF Core 1x和2.x中,它将导致客户端评估,EF Core v3 +将抛出类似于EF 6的异常。

LINQ to Entities最适合表达式。 一旦你需要表达式,你最好让自定义扩展方法直接接收lambda表达式,而不是像链接主题中那样通过lambda表达式获得PropertyInfo

以下是上述示例实现:

public static partial class QueryableExtensions
{
    public static IQueryable<T> WhereMatch<T>(this IQueryable<T> source, Expression<Func<T, string>> expr, string searchValue)
    {
        if (string.IsNullOrEmpty(searchValue))
            return source;
        else if (searchValue.Contains("%"))
            return source.Where(expr.Map(value => EF.Functions.Like(value, searchValue)));
        else
            return source.Where(expr.Map(value => value == searchValue));
    }

    static Expression<Func<TSource, TTarget>> Map<TSource, TIntermediate, TTarget>(this Expression<Func<TSource, TIntermediate>> source, Expression<Func<TIntermediate, TTarget>> target)
        => Expression.Lambda<Func<TSource, TTarget>>(Expression.Invoke(target, source.Body), source.Parameters);
}

主要方法是WhereMatch 它使用一个名为Map的小型Expression辅助方法来编写来自其他lambda表达式的lambda表达式。

示例用法是:

// SearchPerson searchPerson
// DbContext db
var query = db.Set<Person>()
    .WhereMatch(p => p.Name, searchPerson.Name)
    .WhereMatch(p => p.MothersName, searchPerson.MothersName)
    .WhereMatch(p => p.FathersName, searchPerson.FathersName);

对于Equality比较,你应该使用==

EFPersonObject.Where(m => m.Name == searchPerson.Name);

对于LIKE

like 'something%' :( StartsWith Method)

EFPersonObject.Where(m => m.Name.StartsWith(searchPerson.Name));

like '%something' :( EndsWith Method)

EFPersonObject.Where(m => m.Name.EndsWith(searchPerson.Name));

like '%something%' :( Contains方法)

EFPersonObject.Where(m => m.Name.Contains(searchPerson.Name));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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