簡體   English   中英

LINQ的多個搜索參數

[英]Multiple search parameters with LINQ

我正在寫我認為應該是一個相對簡單的Windows Form應用程序。 我正在使用LINQ to SQL,盡管之前從未使用過。 我們有一個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;
}

我意識到從語法上講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;
}

根據LINQ動態查詢庫文章,這應該可以。 這是我得到的錯誤:

無法從用法中推斷出方法'System.Linq.Queryable.Where(System.Linq.IQueryable,System.Linq.Expressions.Expression>)'的類型參數。 嘗試顯式指定類型參數。

這是一個使用動態LINQ查詢庫的示例(我剛剛對其進行了測試)。

using System.Linq.Dynamic;
// ...

Dictionary<string, string> searchParams = new Dictionary<string,string>();

searchParams.Add("EmployeeID", "78");
searchParams.Add("EmpType", "\"my emp type\"");

IQueryable<Employee> query = context.Employees;

foreach (KeyValuePair<string, string> keyValuePair in searchParams)
{
    query = query.Where(string.Format("{0} = {1}", keyValuePair.Key,  keyValuePair.Value));
}

List<Employee> employees = query.ToList();

並且,要明確說明此代碼實際上在這里有效,是實際生成的SQL:

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

如果由於某些原因不需要字典,我將使您的Search方法如下:

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

然后,您將使用如下方法:

Obj.Search( item => item.Property1 == "Hello" && item.Property2 == "World" );

有某些原因導致您無法執行此操作?

[編輯:添加了AsQueryable()]

[編輯:使用字符串進行動態查詢]

在這里看看,是否有幫助。 我沒有使用過,但是看起來它就是您要尋找的東西: http : //weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the- linq-動態查詢-library.aspx

就個人而言,我通常更喜歡使用類型安全的Expression>方法,因為這會給您帶來編譯時錯誤……但是,如果需要字符串,那么這似乎是最好的方法。

根據以上鏈接,您應該可以執行以下操作:

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

這只會在第一個條件之后使用“ AND”。 希望能幫助到你...

僅供參考-這是題外話,但我為什么使用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);
}

您可以像這樣使用它:

Search(p => p.Name == "Name" && p.Id == 0);

您也將不僅限於字符串屬性。

您是否嘗試在字符串中加上單引號? 根據您的foreach循環,查詢末尾會有額外的“ AND”

試試這個代替

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

如果您願意創建可搜索術語的詞典,而不是我使用了與以下方法相似的方法。 我已經將我所做的工作更適應於您的工作方式,還更改了表的名稱以適合我可以使用的datacontext / object模型。

這個想法是創建查詢支持的關鍵詞的關鍵字列表。 然后添加返回表達式的函數,然后可以將該表達式傳遞到查詢的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;
}

用於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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM