2016-01-23 29 views
0

我想通過IQueryable作爲參數傳遞給一個函數,然後將調用實體框架提供如下執行查詢:如何將IQueryables合併爲一個調用?

public ICollection<MyRowType> RunCommand(IQueryable<MyRowType> query) 
{ 
    using (var db = new MyDbContext()) 
    { 
     var result = db.MyRowType 
      .Include(r => r.RelatedTableA) 
      .Include(r => r.RelatedTableB) 
      .Include(r => r.RelatedTableC) 

      // How do I make the value in `query` run here? 

      .ToList(); 
    } 
} 

我基本上環繞我的數據庫調用此方法返回所有必要的包括但我不想失去通過IQueryable<MyRowType>進行自定義查詢的靈活性。

這裏是想什麼,我實現一個例子:

public ICollection<MyRowType> SomeOtherMethod(string id, SomeValue value = null, SomeOtherValue otherValue = null) 
{ 
    var query = Enumerable.Empty<MyRowType>() 
     .Where(r => r.Id == di); 

    if (value != null) 
     query = query.Where(r => r.PropertyOne == value); 

    if (otherValue != null) 
     query = query.Where(r => r.PropertyTwo == otherValue); 

    return RunCommand(query);  
} 

答案更新:

我的Yacoub Massaddasblinkenlight的答案組合成這兩種方法:

public static ICollection<MyRowType> RunCommand(Expression<Func<MyRowType, bool>> condition) 
{ 
    return Get(t => t.Where(condition)); 
} 

public static ICollection<MyRowType> RunCommand(Func<IQueryable<MyRowType>, IQueryable<MyRowType>> query) 
{ 
    using (var db = new DbContext()) 
    { 
     var includes = db.MyRowType 
      .Include(r => r.RelatedTableA) 
      .Include(r => r.RelatedTableB) 
      .Include(r => r.RelatedTableC) 

     var result = query(includes) 
      .ToList(); 

     return result; 
    } 
} 
+0

你能給你想傳遞一個查詢的例子嗎? –

回答

1

您應該通過Func<IQueryable<MyRowType>,IQueryable<MyRowType>>而不是IQueryable<MyRowType>像這樣:

public ICollection<MyRowType> RunCommand(Func<IQueryable<MyRowType>,IQueryable<MyRowType>> func) 
{ 
    using (var db = new MyDbContext()) 
    { 
     IQueryable<MyRowType> q = db.MyRowType 
      .Include(r => r.RelatedTableA) 
      .Include(r => r.RelatedTableB) 
      .Include(r => r.RelatedTableC); 

     var result = func(q); 

     return result.List(); 
    } 
} 

然後你就可以使用它像這樣:

var result = RunCommand(q => q.Where(....)); 

或使用其他LINQ的方法是這樣的:

var result = RunCommand(q => q.Where(....).OrderBy(x => ...).Take(10)); 

請注意,你不能將一個查詢,將選擇不同類型的比MyRowType。如果你想要的話可​​以使該方法一般是這樣的:

public ICollection<T> RunCommand<T>(Func<IQueryable<MyRowType>,IQueryable<T>> func) 
{ 
    using (var db = new MyDbContext()) 
    { 
     IQueryable<MyRowType> q = db.MyRowType 
      .Include(r => r.RelatedTableA) 
      .Include(r => r.RelatedTableB) 
      .Include(r => r.RelatedTableC); 

     var result = func(q); 

     return result.List(); 
    } 
} 

現在你可以使用這樣的:

var result = RunCommand<SomeOtherType>(q => q.Where(x => ....).Select(x => ....)); 
1

這是不容易從IQueryable<T>提取的表達,你止跌無法直接應用您傳入方法的queryable。但是,因爲它似乎您試圖通過傳遞IQueryable<T>不改變輸出類型來限制查詢,可能會更容易改變API採取的條件,而不是IQueryable<T>,像這樣:

public ICollection<MyRowType> RunCommand(Expression<Func<MyRowType,bool>> condition) { 
    using (var db = new MyDbContext()) { 
     var result = db.MyRowType 
      .Include(r => r.RelatedTableA) 
      .Include(r => r.RelatedTableB) 
      .Include(r => r.RelatedTableC) 
      .Where(condition) 
      .ToList(); 
    } 
} 

如果您使用LINQ to Entities predicate combiner你將能夠自定義條件與RunCommand方法內部執行的常用製備步驟組合:

public ICollection<MyRowType> SomeOtherMethod(string id, SomeValue value = null, SomeOtherValue otherValue = null) { 
    Expression<Func<MyRowType,bool>> condition = 
     r => r => r.Id == di; 
    if (value != null) 
     condition = condition.And(r => r.PropertyOne == value); 
    if (otherValue != null) 
     condition = condition.And(r => r.PropertyTwo == otherValue); 
    return RunCommand(query);  
} 
+0

我有一個方法的重載,如您所述的那樣需要一個條件。我希望能夠傳遞像'FirstOrDefault'或多個'Where'這樣的子句自己構造的東西。在一個側面說明中,你的例子幫助我解決了一個問題,如果我傳遞了一個'Func '它在命中數據庫之後執行條件,非常感謝。 – Omar

+0

對於FirstOrDefault你是對的,我想給其他方法基於他們自己的邏輯構建IQueryable的能力。我會爲我的問題添加一個例子。 – Omar

+0

@Omar你應該能夠將你的例子(包含多個'Where'子句)放入'Expression >方法中。 – dasblinkenlight

相關問題