2008-10-24 82 views
9

聲明:我已經使用System.Linq.Expressions中的表達式解決了該問題,但我仍在尋找更好/更簡單的方法。LINQ中的動態where子句 - 列名在運行時可用

考慮以下情況:

var query = 
    from c in db.Customers 
    where (c.ContactFirstName.Contains("BlackListed") || 
      c.ContactLastName.Contains("BlackListed") || 
      c.Address.Contains("BlackListed")) 
    select c; 

列/需要對列入黑名單的期限進行檢查屬性只適用於我在運行時。我如何生成這個動態where子句?

另一個複雜的問題是,Queryable集合(db.Customers上面)被鍵入到'Customer'的基類(稱爲'Person')的Queryable中,因此如上所述編寫c.Address不是一個選項。

+4

我很想看看您的Expressions解決方案,有機會添加到您的答案?乾杯。 – Kev 2008-10-24 17:18:11

+0

看到這個[問題](http://stackoverflow.com/questions/30879/is-there-a-pattern-using-linq-to-dynamically-create-a-filter)和我的後續答案有關動態LINQ查詢 – Geoff 2008-10-24 17:18:50

回答

7
var query = from C in db.Customers select c; 

if (seachFirstName) 
     query = query.Where(c=>c.ContactFirstname.Contains("Blacklisted")); 

if (seachLastName) 
     query = query.Where(c=>c.ContactLastname.Contains("Blacklisted")); 

if (seachAddress) 
     query = query.Where(c=>c.Address.Contains("Blacklisted")); 

請注意,它們不是互斥的。

0

由於這不是LINQ到對象,而是LINQ to SQL,除了使用表達式或存儲過程外,沒有其他選擇。

13

@Geoff擁有最佳的選擇,即將推出Dynamic LINQ。

如果你想使用lambda去建立查詢的方式運行時,雖然我是電子書籍使用PredicateBuilder(http://www.albahari.com/nutshell/predicatebuilder.aspx),並有一些像這樣的:

Expression<Fun<T,bool>> pred = null; //delcare the predicate to start with. Note - I don't know your type so I just used T 
if(blacklistFirstName){ 
    pred = p => p.ContactFirstName.Contains("Blacklisted"); 
} 
if(blacklistLastName){ 
    if(pred == null){ 
    pred = p => p.ContactLastName.Contains("Blacklisted"); //if it doesn't exist just assign it 
    }else{ 
    pred = pred.And(p => p.ContactLastName.Contains("Blacklisted"); //otherwise we add it as an And clause 
    } 
} 

等了所有你想包括的列。當你到你的查詢,你只需要像這樣:

var results = db.Customers.Where(pred).Select(c => c); 

我用這個來的,那裏有大約20個不同的選項,它會產生真正的好SQL搜索做LINQ的建設。

2

您可以使用某些邏輯表達式來打開和關閉where子句。

//Turn on all where clauses 
bool ignoreFirstName = false; 
bool ignoreLastName = false;; 
bool ignoreAddress = false; 

//Decide which WHERE clauses we are going to turn off because of something. 
if(something) 
    ignoreFirstName = true; 

//Create the query 
var queryCustomers = from c in db.Customers 
    where (ignoreFirstName || (c.ContactFirstName.Contains("BlackListed"))) 
    where (ignoreLastName || (c.ContactLastName.Contains("BlackListed"))) 
    where (ignoreAddress || (c.Address.Contains("BlackListed")) 
    select j; 

如果ignoreFirstName是在查詢真,則上的或陳述對方的條件將被忽略。