黃偉榮的學習筆記

軟體的世界變化萬千,小小的我只能在這洪流奮發向上以求立足。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[小技巧]Entity Framework強型別Include

Posted on 2010-10-20 22:00  黃偉榮  阅读(537)  评论(0编辑  收藏  举报

在Entity Framework中如果不設定為Lazy Loading Enable=true,勢必要自己處理關聯資料的載入,如:用Load或Include的,但因為Include的參數是用string,個人很討厭沒有IntelliSense,且用String改了TableName後,工具不易找到錯誤,所以小弟我寫一個Extension Method來擴展。

//原弱型別的寫法
AdventureWorksLT2008R2Entities context = new AdventureWorksLT2008R2Entities();
var customer = context.Customer.Include("SalesOrderHeader").ToList();

//擴展的強型別寫法
AdventureWorksLT2008R2Entities context = new AdventureWorksLT2008R2Entities();
var customer = context.Customer.Include(x => x.SalesOrderHeader).ToList();

NOTE:

這個方法暫時不適用Collection後又在關聯,如上一個例子SalesOrderHeader是Collection,無法這樣下x.SalesOrderHeader.SalesOrderDetail,為什麼是暫時,因為小弟還沒想出好的寫法,用x.SalesOrderHeader[0].SalesOrderDetail或x.SalesOrderHeader.First().SalesOrderDetail嗎,感覺挺醜的。

Source Code

public static IQueryable<T> Include<T>(this ObjectSet<T> source, Expression<Func<T, object>> path) where T : class
{
    //偷吃步的作法,如:Expression為x=>x.Customer.CustomerAddress,ToString後直接從第一個.分割,取後面的Customer.CustomerAddress
    string spath = path.Body.ToString();
    spath = spath.Substring(spath.IndexOf('.') + 1);
    return source.Include(spath);
}

上面的Code比較偷懶,應該要分析一下Expression比較正統

public static IQueryable<T> Include<T>(this ObjectSet<T> source, Expression<Func<T, object>> path) where T : class
{
    StringBuilder pathBuilder = new StringBuilder();

    MemberExpression pro = path.Body as MemberExpression;
    while (pro != null)
    {
        //Exprssion有點像鏈結串列,從Statemant的後方往前連結,如: x=> x.Customer.CustomerAddress
        //path.Body是CustomerAddress
        //CustomerAddress的Expression是Customer
        //Customer的Expression是x
        pathBuilder.Insert(0, "." + pro.Member.Name);
        pro = pro.Expression as MemberExpression; 
    }

    return source.Include(pathBuilder.ToString(1, pathBuilder.Length-1));
}

NOTE:

我沒有做錯誤檢查,想說有錯Entity Framework也會丟Exception,自己就不多事了。

圖1 Model關聯圖

image