2014-10-03 37 views
0

我有許多不同的表格,每個表格都有一些常用的列和一些對每個表唯一的列。我使用實體框架來操作這些表,LINQ查詢過濾,排序等。下面的代碼是我正在運行的情況的一個高度簡化的例子。函數可以採取不同的表格,並在公共列上操作

 var filter = "A"; 
     using (var dc = new MyDataEntities()) 
     { 
      var rpt1 = dc.Table1.Where(x => x.Name.StartsWith(filter)); 
      var rpt2 = dc.Table2.Where(x => x.Name.StartsWith(filter)); 
      var rpt3 = dc.Table3.Where(x => x.Name.StartsWith(filter)); 
     } 

如果我決定我想改變StartsWith過濾器包含例如,我必須改變它的3個名額。如果我決定要添加排序,我必須將它添加到3個位置等等(正如您可以猜到,我的實際代碼具有跨多個類的邏輯發生,並且多於3個實例。)

有什麼方法可以編寫一個可以接受任何表並在該表的公共列上操作的函數?所以,我最終的結果會是這樣的:

 using (var dc = new MyDataEntities()) 
     { 
      var rpt1 = Filter(dc.Table1); 
      var rpt2 = Filter(dc.Table2); 
      var rpt3 = Filter(dc.Table3); 
     } 

這樣我可以把對名稱列篩選邏輯上的任何我的表到一個過濾器()函數。想法?

+0

您是否考慮過向您的實體添加接口? 'INamedEntity {string Name {get; set; }'?然後你可以編寫一個保存你的查詢並具有通用查詢方法的類,例如'列表 GetByName (字符串名稱)其中TEntity:class,INamedEntity'。或者返回'IQueryable'來進一步過濾。 – 2014-10-03 15:42:07

+0

是rpt1,rpt2,rpt3全部是相同的類型,與Table1,Table2,Table3相同? – dbarnes 2014-10-03 17:36:31

+0

@dbarnes現在,它們是不同的類型,即rpt1將是IEnumerable ,rpt2是IEnumerable 等。如果將它們彙集到一個通用類型中使得解決方案值得考慮。 – gfrizzle 2014-10-03 17:42:59

回答

2

讓我定義所有參與的類:

public class Table1 
{ 
    public string Name { get; set; } 
} 

public class Table2 
{ 
    public string Name { get; set; } 
} 

public class Table3 
{ 
    public string Name { get; set; } 
} 

,你可以告訴有POCO的會更加複雜,但在這個例子中它應該是罰款:

public class Example 
{ 
    public void Test() 
    { 
     var t1 = new List<Table1>(); 
     var t2 = new List<Table2>(); 
     var t3 = new List<Table3>(); 
     var filter = "hello"; 
     Func<string, bool> filterFunc = (x) => x.StartsWith(filter); 

     var rpt1 = t1.Where(x => filterFunc(x.Name)); 
     var rpt2 = t2.Where(x => filterFunc(x.Name)); 
     var rpt3 = t3.Where(x => filterFunc(x.Name)); 

    } 
} 

正如你所看到的我已經將過濾器抽象爲一個function delegate

現在一個可能的更好的解決方案,取決於這是否真的有意義,是將所有的共享co lumns成一個基類,所有這些派生自:

public class TableCommon 
{ 
    public string Name { get; set; } 
} 

public class Table1 : TableCommon 
{} 

public class Table2 : TableCommon 
{} 

public class Table3 : TableCommon 
{} 


public class Example 
{ 

    public void Test2() 
    { 
     var t1 = new List<Table1>(); 
     var t2 = new List<Table2>(); 
     var t3 = new List<Table3>(); 

     var rpt1 = FilterData(t1); 
     var rpt2 = FilterData(t2); 
     var rpt3 = FilterData(t3); 

    } 

    public IEnumerable<T> FilterData<T>(IEnumerable<T> data) where T : TableCommon 
    { 
     var filter = "hello"; 
     Func<T, bool> pred = (x) => x.Name.StartsWith(filter); 
     return data.Where(pred); 
    } 

} 

什麼是關於這個漂亮的,現在你可以隱藏掉你的過濾邏輯,甚至必須要通過預解碼可變的參數在不同的過濾器來傳遞的能力並允許這個函數更通用。

現在,如果您對使用FilterData上的基類和Type約束的這種方式感到不舒服,那麼您將不得不使用反射,因爲其他原因我必須這樣做,並且它變得非常混亂且不可讀非常快。或者像dynamic linq這可能是非常混亂。

+0

徹底的迴應,非常感謝。我同意第二種解決方案會更好,但是深入瞭解Entity Framework爲這些表生成的代碼的內容遠遠超過了我現在想要咬掉的東西。函數的委託方法至少可以讓我把邏輯抽象到一個地方。再次感謝。 – gfrizzle 2014-10-06 13:55:37

相關問題