2011-03-09 97 views
2

我想在EF4中實現加密列並使用CTP5功能來允許簡單地使用POCO來查詢數據庫。對不起,這是很多的話,但我希望以下給出足夠的解釋需要和問題!如何在LINQ to Entities查詢中實現查詢攔截? (c#)

這樣的大背景下位,而且至今我的進步:

的意圖是,如果您查詢表,而不用使用我們DAL那麼數據是垃圾,但我不想讓開發商擔心如何/何時/如何對數據進行加密。

爲了簡單起見,在此階段我正在假設任何字符串列都將被加密。

現在,我已經成功實現了使用Objectmaterialized事件返回數據以及使用SavingChanges事件進行數據提交。

因此,考慮下面的類:

public class Thing 
{ 

    public int ID { get; set; } 
    [Required] 
    public string Name { get; set; } 
    public DateTime Date { get; set; } 
    public string OtherString { get; set; } 
} 

下面的查詢將返回所有所需的值和POCO物化有明確的數據。

var things = from t in myDbContext.Things 
      select t; 

其中myDbContext.Things是DbSet<Thing>

同樣地,傳遞的Thing一個實例Things.Add()
(有明確的字符串數據在名稱和/或OtherString值)
,然後調用myDbContext.SaveChanges()在字符串到達​​數據存儲區之前對其進行加密。現在

,我的問題是,在此查詢:

var things = from t in myDbContext.Things 
      where t.Name == "Hairbrush" 
      select t; 

這導致未加密的值進行比較,以在數據庫加密值。顯然,我不想從數據庫中獲取所有記錄,實現它們,然後根據任何提供的Where子句過濾結果...所以我需要做的是:截取該查詢並通過加密來重寫它Where子句中的字符串。 所以我已經看了:

  • 編寫查詢供應商,但似乎並不像正確的解決方案... (是嗎?)
  • 寫了我自己的IQueryable包裝DbSet將捕獲表達式,使用表達式樹訪問器運行它,然後將新表達式轉發到DbSet ...

嘗試在兩者都使我有些失落!我更喜歡我認爲的第二種解決方案,因爲它感覺有點整潔,未來可能對其他開發人員更清楚。但我很高興與任何一個更好選項!

我正在努力的主要事情是何時/如何將LINQ表達式應用於對象......我想我自己有點困惑,因爲表達式在IQueryable對象中執行的位置因此我不知道我需要在我的包裝中實現哪種方法,然後獲取並操作正在傳遞的表達式...

我敢肯定我在這裏錯過了一些相當明顯的東西,我正在等待那個燈泡的時刻......但它不會來!

任何幫助將非常感激地收到!

+2

如何使用SQL Server 2008及其透明數據加密? – 2011-03-09 17:29:14

回答

2

想我應該讓你知道我的最終解決方案了。 最後,我去了一個實現了Where方法的包裝類,但沒有完全實現IQueryable的範圍。 LINQ仍然會針對類執行(至少在我希望/需要的範圍內),並將使用LINQ中的表達式調用Where方法。

然後,我將遍歷此ExpressionTree,並在將新的表達式樹轉發給內部DbSet之前用加密值替換我的字符串。然後返回結果。

它非常粗糙,有其侷限性,但適用於我們的特殊情況沒有問題。

感謝, 本

0

您應該使用QueryInterceptor屬性,在SO或Google中搜索此處,並找到有關如何使用它的示例。

一個片段:

[QueryInterceptor("Orders")] 
public Expression<Func<Order, bool>> FilterOrders() 
{ 
    return o => o.Customer.Name == /* Current principal name. */; 
} 

// Insures that the user accessing the customer(s) has the appropriate 
// rights as defined in the QueryRules object to access the customer 
// resource(s). 

[QueryInterceptor ("Customers")] 
public Expression<Func<Customer, bool>> FilterCustomers() 
{ 
    return c => c.Name == /* Current principal name. */ && 
       this.CurrentDataSource.QueryRules.Contains(
       rule => rule.Name == c.Name && 
         rule.CustomerAllowedToQuery == true 
      ); 
} 
+0

嗨達維德,我確實看過'QueryInterceptor',但它似乎只有在使用WCF數據服務時纔有意義。如果實現數據服務是唯一的選擇,那麼我可以這樣做,但我希望儘可能避免它,並且我看不到以其他方式實現QueryInceptor的方式。 – Ben 2011-03-09 17:25:22

+0

這是WCF數據服務的功能。 – 2011-03-09 17:28:41

0

你可以用大衛·福勒的查詢攔截:

https://github.com/davidfowl/QueryInterceptor

一個例子它的使用:

IQueryable的Q = ...; IQueryable modifed = q.InterceptWith(new MyInterceptor());

而且階級MyInterceptor:

保護覆蓋表達VisitBinary(BinaryExpression節點){ 如果(node.NodeType == ExpressionType.Equal){// 變化==來= 回報Expression.NotEqual( node.Left,node.Right); } return base.VisitBinary(node); }