2015-02-08 63 views
1

我有這樣的代碼,運行正常:從Linq到列表使用擴展方法

//我的控制器

public HttpResponseMessage GetUserFavorites(string id) 
{ 

    var response = Request.CreateResponse(); 

    response.Content = new StringContent(JsonConvert.SerializeObject(jobRepository.GetUserFavorites(id))); 
    response.StatusCode = HttpStatusCode.OK; 

    return response; 

} 

//我jobRepository

 public IQueryable<ProfileInfo> GetUserFavorites(string iUserId) 
     { 


      var profiles = from favoriate in db.TB_Res_Favorites 
          join profile in db.TB_Res_Profile on favoriate.ProfileID equals profile.ProfileID 
          where favoriate.UserId == iUserId 

          select new ProfileInfo() 
          { 
           ProfileID = profile.ProfileID, 
           FullName = profile.FullName, 
           Headline = profile.Headline, 
           Location = profile.Location, 
           Industry = profile.Industry, 
           ImageUrl = profile.ImageUrl, 
           EducationInstitute = profile.EducationInstitute, 
           Degree = profile.Degree 
          }; 


      return profiles; 


     } 

的問題是,該映射到ProfileInfo將在我的代碼中的許多地方返回。我顯然想避免這種情況。我想用擴展方法,將從EF映射到我的課是這樣的:

//我的分機:

public static class ModelExtensions 
    { 

     public static ProfileInfo ToProfileInfo(this TB_Res_Profile dbProfile) 
     { 
      return new ProfileInfo 
      { 

       ProfileID= dbProfile.ProfileID, 
       FullName = dbProfile.FullName, 
       Headline = dbProfile.Headline, 
       Location = dbProfile.Location, 
       Industry = dbProfile.Industry, 
       ImageUrl = dbProfile.ImageUrl, 
       EducationInstitute = dbProfile.EducationInstitute, 
       Degree = dbProfile.Degree 
      }; 
     } 




    } 

,並使用它像這樣(CONTROLER不變):

public IQueryable<ProfileInfo> GetUserFavorites(string iUserId) 
{ 


    var profiles = from favoriate in db.TB_Res_Favorites 
        join profile in db.TB_Res_Profile on favoriate.ProfileID equals profile.ProfileID 
        where favoriate.UserId == iUserId 
        select profile.ToProfileInfo(); 


    return profiles; 


} 

是編譯好的,但我得到這個錯誤在運行時間:

「System.NotSupportedException」類型的異常出現在 Newtonsoft.Json.dll但在用戶代碼中沒有處理

其他信息:LINQ到實體無法識別 方法「myApp.Models.InfoClass.ProfileInfo ToProfileInfo(myApp.Models.TB_Res_Profile)」方法,和該方法 不能被翻譯成商店表達。

我知道有我可以使用的自動映射器。但是真的讓我感興趣做這項工作,並明白這裏有什麼問題。

回答

1

您應該通過整個IQueryable並返回另一個IQueryable。事情是這樣的:

public static IQueryable<ProfileInfo> ToProfileInfo(this IQueryable<TB_Res_Profile> query) 
{ 
    return query.Select(p => new ProfileInfo() 
    { 
    ProfileID= p.ProfileID, 
    FullName = p.FullName, 
    Headline = p.Headline, 
    Location = p.Location, 
    Industry = p.Industry, 
    ImageUrl = p.ImageUrl, 
    EducationInstitute = p.EducationInstitute, 
    Degree = p.Degree 
    }); 
} 

現在您只需表達式樹,其中EF會很高興與合作:

var profiles = (from favoriate in db.TB_Res_Favorites 
       join profile in db.TB_Res_Profile 
       on favoriate.ProfileID equals profile.ProfileID 
       where favoriate.UserId == iUserId 
       select profile) 
       .ToProfileInfo(); 
+0

謝謝你,我會用你的答案,小評論:在擴展它應該是xProfileID insPDBProfile.ProfileID等等。 – Ilan 2015-02-08 11:28:56

+1

這就是爲什麼複製/粘貼是邪惡的。謝謝,我已經更新了答案。 – 2015-02-08 11:34:47

1

你可以把它工作中使用擴展方法,如果你第一次強制調用數據庫使用例如ToList()然後用製圖員:

var profiles = (from favoriate in db.TB_Res_Favorites 
       join profile in db.TB_Res_Profile on favoriate.ProfileID equals profile.ProfileID 
       where favoriate.UserId == iUserId 
       select profile).ToList() 
       .Select(p => p.ToProfileInfo()); 
return profiles; 

爲什麼你需要調用數據庫的原因首先,因爲實體框架將您的LINQ代碼翻譯成SQL代碼,並且當它找到自定義的擴展方法時,它顯然不能進行翻譯。

當您使用ToList()強制請求數據庫時,您在C#代碼中請求擴展方法,這顯然是有效的事情。

0

您可以使用導航屬性,如果他們在的地方正確設置,而做這樣的事情:

from p in db.TB_Res_Profile 
where p.TB_Res_Favorite.UserId == iUserId select p; 

這樣你也可以避免所有的映射。介意使用導航屬性的正確名稱。

+0

我試圖避免使用全部的實體TB_Res_Profile,這就是爲什麼我要地圖更小的對象ProfileInfo。 – Ilan 2015-02-10 05:58:14