Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何按多个任意值搜索实体?_C#_Linq_Dynamic_Entity Framework 5 - Fatal编程技术网

C# 如何按多个任意值搜索实体?

C# 如何按多个任意值搜索实体?,c#,linq,dynamic,entity-framework-5,C#,Linq,Dynamic,Entity Framework 5,我有一个客户实体,我希望能够通过多个任意属性搜索该实体的记录 例如: 字典搜索列表=新建字典(); searchList.Add(“LastName”、“Foo”); 搜索列表。添加(“名字”、“栏”); 我当然可以这样写: foreach (KeyValuePair<string, string> kv in searchList) { switch (kv.Key) { case "FirstName" : List<Cu

我有一个
客户
实体,我希望能够通过多个任意属性搜索该实体的记录

例如:

字典搜索列表=新建字典();
searchList.Add(“LastName”、“Foo”);
搜索列表。添加(“名字”、“栏”);
我当然可以这样写:

foreach (KeyValuePair<string, string> kv in searchList)
{
    switch (kv.Key)
    {
       case "FirstName" :
          List<Customer> someResultPart = this._dbSet.Where(customer => customer.FirstName == kv.Value).ToList();
       break;
       case "LastName" :
          // etc.
    }
}

// Do intersection of all result parts ...
foreach(搜索列表中的KeyValuePair)
{
开关(千伏钥匙)
{
案例“名字”:
列出someResultPart=this.\u dbSet.Where(customer=>customer.FirstName==kv.Value).ToList();
打破
案例“LastName”:
//等等。
}
}
//做所有结果部分的交集。。。
除了查询
n
次和稍后进行交叉显然很麻烦之外,我更希望没有
switch
语句(因为这会迫使我在
Customer
类中的任何内容每次更改时都更改它)

有没有办法:

  • “动态”基于
    搜索列表
    字典构建查询,从而消除了
    开关
    构造的需要
  • 将各种条件“连接”到单个db查询中
您可以使用

string谓词=string.Format(“{0}=\{1}\”,kv.Key,kv.Value);
列出someResultPart=_dbSet.Where(谓词);
或者这样:

List<Customer> someResultPart = _dbSet.Where("{0}");
List someResultPart=_dbSet.Where(“{0}”);
我甚至构建了如下的完整搜索谓词:

Dictionary<string, object> searchList = new Dictionary<string, object>();
searchList.Add("LastName", "Foo");
searchList.Add("FirstName", "Bar");
searchList.Add("Id", 42); // yep, not only strings

var conditions = searchList.Select((kvp, i) => String.Format("{0} = @{1}", kvp.Key, i));
string predicate = String.Join(" and ", conditions);
object[] values = searchList.Select(kvp => kvp.Value).ToArray();

var query = _dbSet.Where(predicate, values);
字典搜索列表=新建字典();
searchList.Add(“LastName”、“Foo”);
搜索列表。添加(“名字”、“栏”);
searchList.Add(“Id”,42);//是的,不仅仅是字符串
var conditions=searchList.Select((kvp,i)=>String.Format(“{0}=@{1}”,kvp.Key,i));
字符串谓词=string.Join(“and”,条件);
object[]values=searchList.Select(kvp=>kvp.Value).ToArray();
var query=_dbSet.Where(谓词,值);

关于第二点,您可以:

IQueryable<Customer> filtered = this._dbSet;
foreach (KeyValuePair<string, string> kv in searchList)
{
    switch (kv.Key)
    {
       case "FirstName" :
          filtered = filtered
              .Where(customer => customer.FirstName == kv.Value);
          break;
       case "LastName" :
          // etc.
    }
}
List<Customer> resultList = filtered.ToList();
IQueryable filtered=this.\u dbSet;
foreach(搜索列表中的KeyValuePair kv)
{
开关(千伏钥匙)
{
案例“名字”:
过滤的
其中(customer=>customer.FirstName==kv.Value);
打破
案例“LastName”:
//等等。
}
}
List resultList=filtered.ToList();
注意类型安全

如果有一天您想更改列名,最好构造一个返回良好属性的函数列表,而不是声明一个失败的字符串变量:

    public class Customer { public string FirstName; public string LastName;}
    public class CustomerFilter { public Func<Customer, string> Selector; public string Filter; }
    [TestMethod()]
    public void DynamicFilterTest()
    {
        var jonSkeet = new Customer() { FirstName = "Jon", LastName = "Skeet" };
        var joelOnSoftware = new Customer() { FirstName = "Joel", LastName = "OnSoftware" };
        var customers = new List<Customer>() { jonSkeet, joelOnSoftware };

        var jonSkeetFilters = new List<CustomerFilter>() { 
            new CustomerFilter() { Selector = c => c.LastName, Filter = "Skeet" },
            new CustomerFilter() { Selector = c => c.FirstName, Filter = "Jon" }};
        var query = customers.AsEnumerable();
        foreach (var filter in jonSkeetFilters)
        {
            query = query.Where(c => filter.Selector.Invoke(c) == filter.Filter);
        }
        var result = query.ToList();
        Assert.AreEqual(1, result.Count);
        Assert.AreEqual(jonSkeet, result.Single());
    }
public类客户{public string FirstName;public string LastName;}
公共类CustomerFilter{public Func选择器;公共字符串筛选器;}
[TestMethod()]
public void DynamicFilterTest()
{
var jonSkeet=new Customer(){FirstName=“Jon”,LastName=“Skeet”};
var joelOnSoftware=new Customer(){FirstName=“Joel”,LastName=“OnSoftware”};
var customers=new List(){jonSkeet,joelOnSoftware};
var jonSkeetFilters=new List(){
新建CustomerFilter(){Selector=c=>c.LastName,Filter=“Skeet”},
新建CustomerFilter(){Selector=c=>c.FirstName,Filter=“Jon”};
var query=customers.AsEnumerable();
foreach(jonSkeetFilters中的var过滤器)
{
query=query.Where(c=>filter.Selector.Invoke(c)==filter.filter);
}
var result=query.ToList();
Assert.AreEqual(1,result.Count);
AreEqual(jonSkeet,result.Single());
}
然后,您可以轻松地进行重构,对任何实体使用相同的模式:

public class WhereClause<T>
{
    private readonly Func<T, string> _selector;
    public Func<T, string> Selector { get { return _selector; } }

    private readonly string _value;
    public string Value { get { return _value; } }

    public WhereClause(Func<T, string> selector, string value)
    {
        this._selector = selector;
        this._value = value;
    }

    /// <summary>
    /// Append the where clause to the given query
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    public IEnumerable<T> AppendTo(IEnumerable<T> query)
    {
        return query.Where(c => this.Selector.Invoke(c) == this.Value);
    }


    /// <summary>
    /// Append the wheres clauses to the given query
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    public static IEnumerable<T> AppendTo(IEnumerable<T> query, IEnumerable<WhereClause<T>> wheres)
    {
        var filteredQuery = query;
        foreach (var where in wheres)
        {
            filteredQuery = where.AppendTo(filteredQuery);
        }
        return filteredQuery;
    }
}

[TestClass]
public class WhereClauseTests
{
    public class Customer { public string FirstName; public string LastName;}

    [TestMethod()]
    public void WhereClauseTest()
    {
        var jonSkeet = new Customer() { FirstName = "Jon", LastName = "Skeet" };
        var joelOnSoftware = new Customer() { FirstName = "Joel", LastName = "OnSoftware" };
        var customers = new List<Customer>() { jonSkeet, joelOnSoftware };

        var jonSkeetWheres = new List<WhereClause<Customer>>() { 
            new WhereClause<Customer>(c => c.LastName, "Skeet"),
            new WhereClause<Customer>(c => c.FirstName,  "Jon" )
        };

        var query = WhereClause<Customer>.AppendTo(customers, jonSkeetWheres);

        var result = query.ToList();
        Assert.AreEqual(1, result.Count);
        Assert.AreEqual(jonSkeet, result.Single());
    }
}
public class子句
{
专用只读函数选择器;
公共函数选择器{get{return}
私有只读字符串_值;
公共字符串值{get{return{u Value;}}
public where子句(Func选择器,字符串值)
{
这个._选择器=选择器;
此值为._值=值;
}
/// 
///将where子句追加到给定查询
/// 
/// 
/// 
公共IEnumerable附件(IEnumerable查询)
{
返回query.Where(c=>this.Selector.Invoke(c)==this.Value);
}
/// 
///将wheres子句附加到给定查询
/// 
/// 
/// 
公共静态IEnumerable AppendTo(IEnumerable查询,IEnumerable where)
{
var filteredQuery=query;
foreach(var where in where)
{
filteredQuery=where.AppendTo(filteredQuery);
}
返回filteredQuery;
}
}
[测试类]
公共类条款测试
{
公共类客户{public string FirstName;public string LastName;}
[TestMethod()]
第条测试()项下的公共无效
{
var jonSkeet=new Customer(){FirstName=“Jon”,LastName=“Skeet”};
var joelOnSoftware=new Customer(){FirstName=“Joel”,LastName=“OnSoftware”};
var customers=new List(){jonSkeet,joelOnSoftware};
var jonSkeetWheres=新列表(){
新的WhereClause(c=>c.LastName,“Skeet”),
新WhereClause(c=>c.FirstName,“Jon”)
};
var query=WhereClause.AppendTo(客户、Jonskeetwhere);
var result=query.ToList();
Assert.AreEqual(1,result.Count);
AreEqual(jonSkeet,result.Single());
}
}

Haha@Jon Skeet参考资料。感谢您的回答,非常感谢您的回答,而且您的工作非常出色!是否有任何简单的方法可以搜索嵌套(列表)属性?按照
searchList.Add(“CustomerLikes/CustomerLikedObject.Id”,12345)
?@vzwick从未尝试对嵌套列表使用动态LINQ,您应该自己验证此功能。但它肯定支持嵌套对象,如
地址.Country
    public class Customer { public string FirstName; public string LastName;}
    public class CustomerFilter { public Func<Customer, string> Selector; public string Filter; }
    [TestMethod()]
    public void DynamicFilterTest()
    {
        var jonSkeet = new Customer() { FirstName = "Jon", LastName = "Skeet" };
        var joelOnSoftware = new Customer() { FirstName = "Joel", LastName = "OnSoftware" };
        var customers = new List<Customer>() { jonSkeet, joelOnSoftware };

        var jonSkeetFilters = new List<CustomerFilter>() { 
            new CustomerFilter() { Selector = c => c.LastName, Filter = "Skeet" },
            new CustomerFilter() { Selector = c => c.FirstName, Filter = "Jon" }};
        var query = customers.AsEnumerable();
        foreach (var filter in jonSkeetFilters)
        {
            query = query.Where(c => filter.Selector.Invoke(c) == filter.Filter);
        }
        var result = query.ToList();
        Assert.AreEqual(1, result.Count);
        Assert.AreEqual(jonSkeet, result.Single());
    }
public class WhereClause<T>
{
    private readonly Func<T, string> _selector;
    public Func<T, string> Selector { get { return _selector; } }

    private readonly string _value;
    public string Value { get { return _value; } }

    public WhereClause(Func<T, string> selector, string value)
    {
        this._selector = selector;
        this._value = value;
    }

    /// <summary>
    /// Append the where clause to the given query
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    public IEnumerable<T> AppendTo(IEnumerable<T> query)
    {
        return query.Where(c => this.Selector.Invoke(c) == this.Value);
    }


    /// <summary>
    /// Append the wheres clauses to the given query
    /// </summary>
    /// <param name="query"></param>
    /// <returns></returns>
    public static IEnumerable<T> AppendTo(IEnumerable<T> query, IEnumerable<WhereClause<T>> wheres)
    {
        var filteredQuery = query;
        foreach (var where in wheres)
        {
            filteredQuery = where.AppendTo(filteredQuery);
        }
        return filteredQuery;
    }
}

[TestClass]
public class WhereClauseTests
{
    public class Customer { public string FirstName; public string LastName;}

    [TestMethod()]
    public void WhereClauseTest()
    {
        var jonSkeet = new Customer() { FirstName = "Jon", LastName = "Skeet" };
        var joelOnSoftware = new Customer() { FirstName = "Joel", LastName = "OnSoftware" };
        var customers = new List<Customer>() { jonSkeet, joelOnSoftware };

        var jonSkeetWheres = new List<WhereClause<Customer>>() { 
            new WhereClause<Customer>(c => c.LastName, "Skeet"),
            new WhereClause<Customer>(c => c.FirstName,  "Jon" )
        };

        var query = WhereClause<Customer>.AppendTo(customers, jonSkeetWheres);

        var result = query.ToList();
        Assert.AreEqual(1, result.Count);
        Assert.AreEqual(jonSkeet, result.Single());
    }
}