Linq动态构建查询,没有具体的类型

本文关键字:类型 动态 构建 查询 Linq | 更新日期: 2023-09-27 18:11:55

实际上我正在部署一个通用的搜索控件,这是因为我有许多实体需要被"搜索"

我的方法:一个接口ISearshable

public interface ISearchable
{
    object SearchType { get; }
    string SearchField { get; set; }
    string SearchField2 { get; set; }
    string DisplayField { get; set; }
    decimal SelectedKey { get; set; }
}

类必须像这样实现这个接口:

public partial class PeopleInfoBasica : ISearchable
{
    public string SearchField
    {
        get { return StrSearchKey; }
    }
    public string SearchField2
    {
        get { return StrSearchKeyPhoneDir; }
    }
    public string DisplayField
    {
        get { return StrNombreUsuario; }
    }
    public decimal SelectedKey
    {
        get { return NumIdContrato; }
    }
    public object SearchType
    {
        get { return new PeopleInfoBasica(); }
    }
}

很多人都可以实现它。现在我的通用对象必须像这样处理过滤器:

    private Task PrimerFiltro(string primerfiltro)
    {
        MiContext db = Credentials.Db;
        //  Se aplica el primer filtro a la lista
        var itemsQ = (from i in db.**Here I Need to Specify dynamically the type**
                      where i.SearchField.Contains(primerfiltro)
                      select i
                      ).OrderBy(x => x.DisplayField);
        filteredList = itemsQ.ToList();
        ListaBase = filteredList;
    }

我的问题是:有一种方法来动态指定类型linq?也许还有别的办法?

var itemsQ = (from i in db. 这里我需要动态指定类型where i.SearchField.Contains(primerfiltro) select i ).OrderBy(x => x.DisplayField);

Linq动态构建查询,没有具体的类型

该方案使用SQL查询DB。为了使答案更简短,我擅自去掉了界面。

首先,模型类:
[SearchField("StrSearchKey")]
public partial class PeopleInfoBasica
{
    public string StrSearchKey { get; set; } //The property to search on. Created by EF or code-first
...

}

注意这个带有搜索字段的新属性:

public class SearchFieldAttribute : Attribute
{
    public SearchFieldAttribute(string searchField)
    {
        SearchField = searchField;
    }
    public string SearchField { get; private set; }
}

获取searchField,使用:

var attribute = type.GetCustomAttributes(typeof(SearchFieldAttribute), false).FirstOrDefault() as SearchFieldAttribute;
var searchField = attribute.SearchField;

请在使用前添加安全检查。

结合以上内容,现在您应该能够使用以下命令进行查询:
_db.Set(yourType).SqlQuery(String.Format("SELECT * FROM dbo.{0} WHERE {1} LIKE '%{2}%'", tableName, searchField, primerfiltro))

表名可以从类名或EF中找到。取决于你是否使用CodeFirst,是否有复数等

请注意,我首先尝试了一个解决方案,建立一个表达式树,但它有同样的问题,不能使用OfType()。

我仍然认为最好的解决方案是尝试使您搜索的方法泛型,或者简单地为每个类编写查询。它可能是更多的代码,但它不太容易被破坏。

以上代码容易受到SQL注入的攻击,所以请注意。

让你的方法通用,接受一个类型参数T,它实现了你的ISearchable接口,并添加一个类型参数Expression<Func<T,bool>>,它可以被Queryable.Where()方法使用:

private Task PrimerFiltro<T>(string primerfiltro, Expression<Func<T,bool>> filterExpression) where T: ISearchable
{
    var db = Credentials.Db;
    var set = db.CreateObjectSet<T>();
    var filteredList = set.Where(filterExpression)
                          .OrderBy(x => x.DisplayField)
                          .ToList();
    ListaBase = filteredList;
}

请注意,我正在使用CreateObjectSet()方法来动态获取与类型T对应的实体集。