Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.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# 使用LINQ的多个搜索参数_C#_Linq To Sql - Fatal编程技术网

C# 使用LINQ的多个搜索参数

C# 使用LINQ的多个搜索参数,c#,linq-to-sql,C#,Linq To Sql,我正在写我认为应该是一个相对简单的Windows窗体应用程序。我正在使用LINQtoSQL,尽管我以前从未使用过它。我们有一个SQL Server数据库,我正在创建一个前端来访问该数据库。我正试图找出用它搜索多个(任意数量)搜索参数的最有效方法 在windows窗体中,我用每个搜索键及其要搜索的值创建了一个字典,并将其传递到我的search()方法中。我试图找到一种方法来搜索数据库中的每个键及其相关值。以下是我试图做的: public IQueryable<Product> Sear

我正在写我认为应该是一个相对简单的Windows窗体应用程序。我正在使用LINQtoSQL,尽管我以前从未使用过它。我们有一个SQL Server数据库,我正在创建一个前端来访问该数据库。我正试图找出用它搜索多个(任意数量)搜索参数的最有效方法

在windows窗体中,我用每个搜索键及其要搜索的值创建了一个字典,并将其传递到我的search()方法中。我试图找到一种方法来搜索数据库中的每个键及其相关值。以下是我试图做的:

public IQueryable<Product> Search(Dictionary<string, string> searchParams)
{
   DBDataContext dc = new DBDataContext();
   var query = dc.Products;

   foreach (KeyValuePair<string, string> temp in searchParams)
   {
      query = query.Where(x => x.(temp.Key) == temp.Value);
   }

   return query;
}
公共可查询搜索(字典搜索参数)
{
DBDataContext dc=新的DBDataContext();
var query=dc.Products;
foreach(searchParams中的KeyValuePair临时值)
{
查询=查询,其中(x=>x.(临时键)=临时值);
}
返回查询;
}
我意识到语法上的x(temp.Key)是不正确的,但我希望这能说明我想做什么。我想知道是否有另一种方法来实现我正在尝试的操作,而不必执行一个巨大的switch语句(或者if/else if-tree)

编辑

所以,我对它做了一点修改,但仍然有一些问题。以下是我目前拥有的:

public IQueryable<Product> Search(Dictionary<string, string> searchParams)
{
    DBDataContext dc = new DBDataContext();

    string sQuery = "";
    foreach (KeyValuePair<string, string> temp in searchParams)
    {
        sQuery += temp.Key + "=" + temp.Value + " AND ";
    }

    var query = dc.Products.Where(sQuery);

    return query;
}
公共可查询搜索(字典搜索参数)
{
DBDataContext dc=新的DBDataContext();
字符串sQuery=“”;
foreach(searchParams中的KeyValuePair临时值)
{
sQuery+=临时键+“=”+临时值+”和“;
}
var query=dc.Products.Where(sQuery);
返回查询;
}
根据LINQ动态查询库的文章,这应该是可以的。下面是我得到的错误:


无法根据用法推断方法“System.Linq.Queryable.Where(System.Linq.IQueryable,System.Linq.Expressions.Expression>)”的类型参数。请尝试显式指定类型参数。

如果出于某种原因不需要词典,我将按如下方式创建您的搜索方法:

public IQueryable<Product> Search( Func<Product, bool> isMatch )
{
   DBDataContext dc = new DBDataContext();
   return dc.Products.Where( isMatch ).AsQueryable();
}
你有什么理由不能那样做吗

[编辑:添加了AsQueryable()]

[编辑:用于使用字符串的动态查询]

看看这里,看看这是否有帮助。我没用过,但看起来这正是你想要的:

就个人而言,我通常更喜欢类型安全表达式>方法,因为这会给您带来编译时错误……但是如果需要字符串,那么看起来是最好的方法

根据以上链接,您应该能够执行以下操作:

query = query.Where( String.Format("{0}={1}",dict.Key,dict.Value) );
[编辑:字符串构建示例]

因此,其中一个问题是,sql查询将以AND结尾,但在字符串末尾没有条件…因此,可以尝试更改为此…语法可能会稍微关闭,但应该是正确的:

public IQueryable<Product> Search(Dictionary<string, string> searchParams)
{
    DBDataContext dc = new DBDataContext();

    StringBuilder sQuery = new StringBuilder();
    foreach (KeyValuePair<string, string> temp in searchParams)
    {
        if( sQuery.Length > 0 ) sQuery.Append(" AND ");
        sQuery.AppendFormat("{0}={1}",temp.Key,temp.Value);
    }

    var query = dc.Products.Where(sQuery.ToString());

    return query;
}
公共可查询搜索(字典搜索参数)
{
DBDataContext dc=新的DBDataContext();
StringBuilder sQuery=新的StringBuilder();
foreach(searchParams中的KeyValuePair临时值)
{
如果(sQuery.Length>0)sQuery.Append(“AND”);
追加格式(“{0}={1}”,临时键,临时值);
}
var query=dc.Products.Where(sQuery.ToString());
返回查询;
}
这将仅在第一次之后的条件下使用“和”。希望对你有帮助


仅供参考-这不是主题,但是“为什么”我使用StringBuilder是因为字符串连接的方式会导致字符串被销毁,并且每个循环在内存中创建4次新字符串…因此改为StringBuilder,因为这将创建一个缓冲区,只有在必要时才可以填充和调整大小。

而不是使用字典,您可以使用以下方法:

using System.Linq.Expressions;
// ...

public static IQueryable<Product> Search(Expression<Func<Product, bool>> search)
{
    DBDataContext dc = new DBDataContext();
    return dc.Products.Where(search);
}

您也不会局限于字符串属性。

下面是一个使用


你试过为你的字符串加上单引号吗? 根据您的foreach循环,在查询的末尾将有额外的“AND”

试试这个

string sQuery = searchParam.Select(entry => string.Format("{0} = '{1}'", entry.Key, entry.Value)).Aggregate((current, next) => current + " AND " next);

如果您愿意创建一个可搜索术语词典,那么我已经使用了类似下面的方法。我已经调整了我所做的事情,使之更符合您的工作方式,我还更改了表的名称,以适合我可用的datacontext/对象模型

这样做的目的是创建一个关键字列表,您的查询支持按其进行搜索。然后添加返回表达式的函数,该表达式可以传递到查询的where子句中

当然,您应该为无效密钥等添加一些错误处理

public IQueryable<Person> Search(Dictionary<string, string> searchParams)
{
    DBDataContext dc = new DBDataContext();
    var query = dc.Persons.Where(p => true); //do an 'empty predicate' because you want 'query' to be an iqueryable<Person> not a Table<Person>

    //build a list of the types of things you can filter on.
    var criteriaDefinitions = new Dictionary<string,Func<string,Expression<Func<Person,bool>>>>();
    criteriaDefinitions.Add("FirstName",s => p => p.FirstName == s);
    criteriaDefinitions.Add("LastName",s => p => p.LastName == s);

    //you can do operations other than just equals
    criteriaDefinitions.Add("EmailContains",s => p => p.Email.Contains(s));

    //you can even create expressions that integrate joins.
    criteriaDefinitions.Add("HasContactInCity",s => p => p.Contacts.Any(c => c.City == s));


    foreach (KeyValuePair<string, string> temp in searchParams)
    {
        //grab the correct function out of the dictionary
        var func = criteriaDefinitions[temp.Key];

        //evaluating the function will return an expression which can passed into the where clause.
        var expr = func(temp.Value);
        query = query.Where(expr);
    }

    return query;
}
公共可查询搜索(字典搜索参数)
{
DBDataContext dc=新的DBDataContext();
var query=dc.Persons.Where(p=>true);//执行“空谓词”,因为您希望“query”是iqueryable而不是表
//建立一个列表,列出你可以过滤的事物类型。
var criteriaDefinitions=新字典();
添加(“FirstName”,s=>p=>p.FirstName==s);
添加(“LastName”,s=>p=>p.LastName==s);
//你可以做一些不只是相等的运算
添加(“EmailContains”,s=>p=>p.Email.Contains);
//您甚至可以创建集成联接的表达式。
添加(“HasContactInCity”,s=>p=>p.Contacts.Any(c=>c.City==s));
foreach(searchParams中的KeyValuePair临时值)
{
//从字典中找出正确的函数
var func=标准定义[temp.Key];
//对函数求值将返回一个表达式,该表达式可以传递到where子句中。
变量表达式=函数(温度值);
query=query.Where(expr);
}
返回查询;
}

用于linq搜索查询多个可选参数 可以使用以下代码:

var query = dx.GetAllJobs().Where(x => x.JobName.Contains(keyword));

if (SecLink != 0)
{
    query = query.Where(x => x.SectorLink.Equals(SecLink));
}

if (LocLink != 0)
{
    query = query.Where(x => x.LocationLink.Equals(LocLink));
}

if (IndLink != 0)
{
    query = query.Where(x => x.IndustryLink.Equals(IndLink));
}

if (VacLink != 0)
{
    query = query.Where(x => x.VacancyTypeLink.Equals(VacLink));
}

var lstJobs = query.ToList();

搜索方法参数需要是一个字典而不是一个Func,这有什么原因吗???不完全确定这是什么意思。。。你能澄清一下吗?字典里的每一个键都有段落
FROM [HumanResources].[Employee] AS [t0]
WHERE ([t0].[EmpType] = @p0) AND ([t0].[EmployeeID] = @p1)',N'@p0 nvarchar(11),@p1 int',@p0=N'my emp type',@p1=78
string sQuery = searchParam.Select(entry => string.Format("{0} = '{1}'", entry.Key, entry.Value)).Aggregate((current, next) => current + " AND " next);
public IQueryable<Person> Search(Dictionary<string, string> searchParams)
{
    DBDataContext dc = new DBDataContext();
    var query = dc.Persons.Where(p => true); //do an 'empty predicate' because you want 'query' to be an iqueryable<Person> not a Table<Person>

    //build a list of the types of things you can filter on.
    var criteriaDefinitions = new Dictionary<string,Func<string,Expression<Func<Person,bool>>>>();
    criteriaDefinitions.Add("FirstName",s => p => p.FirstName == s);
    criteriaDefinitions.Add("LastName",s => p => p.LastName == s);

    //you can do operations other than just equals
    criteriaDefinitions.Add("EmailContains",s => p => p.Email.Contains(s));

    //you can even create expressions that integrate joins.
    criteriaDefinitions.Add("HasContactInCity",s => p => p.Contacts.Any(c => c.City == s));


    foreach (KeyValuePair<string, string> temp in searchParams)
    {
        //grab the correct function out of the dictionary
        var func = criteriaDefinitions[temp.Key];

        //evaluating the function will return an expression which can passed into the where clause.
        var expr = func(temp.Value);
        query = query.Where(expr);
    }

    return query;
}
var query = dx.GetAllJobs().Where(x => x.JobName.Contains(keyword));

if (SecLink != 0)
{
    query = query.Where(x => x.SectorLink.Equals(SecLink));
}

if (LocLink != 0)
{
    query = query.Where(x => x.LocationLink.Equals(LocLink));
}

if (IndLink != 0)
{
    query = query.Where(x => x.IndustryLink.Equals(IndLink));
}

if (VacLink != 0)
{
    query = query.Where(x => x.VacancyTypeLink.Equals(VacLink));
}

var lstJobs = query.ToList();