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

时间:2014-07-07 19:49:12

标签: c# linq

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

我的aproach: interfase ISearshable

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

clases必须实现这样的interfase:

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

2 个答案:

答案 0 :(得分:2)

使您的方法通用接受实现T接口的类型参数ISearchable,并添加可由Queryable.Where()方法使用的Expression<Func<T,bool>>类型的参数:

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类型对应的实体集。

答案 1 :(得分:2)

此解决方案使用SQL查询数据库。我已经放弃了界面来缩短答案。

首先,模型类:

[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注入攻击,所以请注意。