2011-06-27 51 views
1

我知道有一種方法可以使用表達式和Lambdas來完成這個任務,但我很難將它們拼湊在一起。我所需要的只是一個動態查詢實體框架DBSet對象的方法,以查找具有給定名稱的propery與該值匹配的行。實體框架4.1簡單的動態表達式object.property =值

我的背景:

public class MyContext : DbContext 
{ 
    public IDbSet<Account> Accoounts{ get { return Set<Account>(); } } 
} 

的方法,我在找寫:

public T Get<T>(string property, object value) : where T is Account 
{...} 

我寧可不要使用動態SQL來完成這個所以沒有必要建議,因爲我已經知道這是可能的。我真正想要的是使用表達式和Lambdas來實現這一點的一些幫助。

在此先感謝,我知道它很簡短,但它應該是不言而喻的。評論是否需要更多信息

回答

1

動態Linq可能是一個選項。將您的條件指定爲字符串,並將其作爲表達式構建並針對您的數據運行;

我從事的一些事例;

var context = new DataContext(ConfigurationManager.ConnectionStrings["c"].ConnectionString); 
var statusConditions = "Status = 1"; 
var results = (IQueryable)context.Contacts.Where(statusConditions); 

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

2

我試圖避免動態LINQ儘可能因爲LINQ的主要點是強類型的訪問。使用動態LINQ是一個解決方案,但它恰恰是與LINQ目的相對的,它非常接近使用ESQL並通過串聯構建查詢。無論如何,動態LINQ有時是實時的節省(特別是當涉及到複雜的動態排序時),我成功地將它用於Linq-to-Sql的大型項目中。

我最常做的就是定義一些SearchCriteria類,如:

public class SearchCriteria 
{ 
    public string Property1 { get; set; } 
    public int? Property2 { get; set; } 
} 

和輔助查詢擴展方法,如:

public static IQueryable<SomeClass> Filter(this IQueryable<SomeClass> query, SearchCriteria filter) 
{ 
    if (filter.Property1 != null) query = query.Where(s => s.Property1 == filter.Property1); 
    if (filter.Property2 != null) query = query.Where(s => s.Property2 == filter.Property2); 
    return query; 
} 

它不是通用的解決方案。同樣的通用解決方案是針對某些類的強類型處理來共享某些行爲。

更復雜的解決方案是使用謂詞構建器並自己構建表達式樹,但再次構建表達式樹只是通過連接字符串來構建ESQL查詢的更復雜的方法。

1

這裏是我的實現:

public T Get<T>(string property, object value) : where T is Account 
{ 
    //p 
    var p = Expression.Parameter(typeof(T)); 

    //p.Property 
    var propertyExpression = Expression.Property(p, property); 

    //p.Property == value 
    var equalsExpression = Expression.Equal(propertyExpression, Expression.Constant(value)); 

    //p => p.Property == value 
    var lambda = Expression.Lambda<Func<T,bool>>(equalsExpression, p); 

    return context.Set<T>().SingleOrDefault(lambda); 
} 

它使用EF 5的Set<T>()方法。如果您使用的版本較低,則需要實施基於<T>類型獲取DbSet的方法。

希望它有幫助。