場景
最近對爬蟲的數據庫架構做調整,需要將數據遷移到MongoDB上去,需要重新實現一個針對MongoDB的Dao泛型類,好吧,動手開工,當實現刪除操作的時候問題來了。
我們的刪除操作定義如下:void Delete(TEntity entity)
。TEntity是我們的泛型類。
而MongoDB官方驅動自帶的刪除操作是這樣的:
1
2
3
// 假設數據模型為已定義的Article
var query = Query<Article>.EQ(t => t.Id, id);
coll.Remove(query);
Dao操作的接口是不能修改的,這就要求我們必須實現以下操作:
- 獲取entity的Id值
- 構造lambda表達式用於獲取Id屬性
實現
對於第1個好辦,直接通過反射拿就可以了,至於第2個構造lambda表達式卻不知該如何下手了。
在網上查資料了解到C# Lambda表達式樹允許我們像處理數據(比如讀取,修改)一樣來處理Lambda表達式。
。這就有方向了,研究了一下表達式樹的相關知識,歷經坎坷終於將其實現。
我用到的lambda表達式比較簡單,也容易構造,代碼中看注釋應該就明白了,代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/// <summary>
/// 因為使用的Mongodb,每個數據模型必定包含Id屬性,通過Id屬性來刪除實體
/// </summary>
/// <param name="entity"></param>
public void Delete(TEntity entity)
{
var coll = _db.GetCollection<TEntity>(typeof(TEntity).Name);
if (entity == null)
{
return;
}
ObjectId id = (ObjectId)typeof(TEntity).GetProperty("Id").GetValue(entity, null);
// 通過表達式樹構造lambda表達式{t => t.Id}
// 構造調用目標t
var target = Expression.Parameter(typeof(TEntity), "t");
// 構造對t的屬性Id的表達式
MemberExpression bodyExp = Expression.Property(
target,
"Id");
// 構造完整的lambda表達式
Expression<Func<TEntity, ObjectId>> selector =
Expression.Lambda<Func<TEntity, ObjectId>>(bodyExp, new [] { target });
// 使用泛型前的語句: Query<Article>.EQ(t => t.Id, id);
var query = Query<TEntity>.EQ(selector, id);
coll.Remove(query);
}
參考資料
用到的工具
之前都是直接使用lambda表示,而且用的還很Happy,今天遇到的問題,讓我很傻眼,基礎還得鞏固啊。今天也是第一次調試lambda表達式,用到了Expression Tree Visualizer for VS 2010這個小工具。在項目調試過程中可以比較直觀的查看編譯好的lambda表達式。
安裝和使用方法,請參見:在Visual Studio 2010設置Expression Tree Visualizer