最近在學習EDM,發現LinqPad是一個好東西,可以運行Linq To Sql, Entity SQL Language腳本,但不會用ESql查詢功能,始終報錯,半天找不到門道,一怒之下決定自己寫一個小型的ESql查詢器。
將比較重要的知識點歸納了一下,貼幾段重要的代碼,以免下次遺忘。
private void btnRunQuery_Click(object sender, EventArgs e)
{
if (cmbEntitySet.SelectedItem == null)
return;
Type typeObjectQuery = (cmbEntitySet.SelectedItem as ImageComboBoxItem).Value as Type;
Type typeEntity = typeObjectQuery.GetGenericArguments()[0];
using (cdms3Entities ctx = new cdms3Entities())
{
//通過反射調用ObjectQuery<T> CreateQuery<T>(string queryString, params ObjectParameter[] parameters);
MethodInfo miCreateQuery = ctx.GetType().GetMethod("CreateQuery", BindingFlags.Instance | BindingFlags.Public);
//設置CreateQuery<T>中的T泛型參數為typeEntity所指的實體對象類型
miCreateQuery = miCreateQuery.MakeGenericMethod(typeEntity);
//創建調用參數,傳入Entity SQL Language語句
object[] args = new object[] { mmeESql.Text, new ObjectParameter[] { } };
//調用CreateQuery函數,返回一個ObjectQuery<T>類型的對象,ObjectQuery<T>泛型類由ObjectQuery類派生,所以可轉換為ObjectQuery類型
ObjectQuery oq = miCreateQuery.Invoke(ctx, args) as ObjectQuery;
//如果下列檢查框中有選擇需要Include到查詢中的實體對象
if (cmbIncludes.Properties.GetCheckedItems() != "")
{
//獲取ObjectQuery<T> Include(string path);函數,注意函數的返回值類型是泛型,但函數並不是泛型,所以不需要也不能對其調用MakeGenericMethod方法
MethodInfo miInclude = oq.GetType().GetMethod("Include", BindingFlags.Instance | BindingFlags.Public);
foreach (CheckedListBoxItem item in cmbIncludes.Properties.Items)
{
if (item.CheckState == CheckState.Checked)
{
EntityObjectInfo eo = item.Value as EntityObjectInfo;
args = new object[] { eo.Path };
//調用ObjectQuery<T>.Include方法
oq = miInclude.Invoke(oq, args) as ObjectQuery;
}
}
}
//下面調用ObjectQuery<T>.ToList()方法來獲取查詢結果。
//特別要注意的是ToList()方法是一個擴展方法,方法原型是:public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source);位於System.Linq.Enumerable類
//所以反射時應當對Enumerable類進行,且該方法為公共靜態方法。
MethodInfo miToList = typeof(Enumerable).GetMethod("ToList", BindingFlags.Static | BindingFlags.Public);
miToList = miToList.MakeGenericMethod(typeEntity);
args = new object[] { oq };
object o = miToList.Invoke(null, args);
//var q = ctx.CreateQuery<Department>(mmeESql.Text);
mmeTraceSql.Text = oq.ToTraceString();
grdResultData.DataSource = o;
}
}