从Linq到列表使用扩展方法

时间:2015-02-08 08:27:58

标签: c# linq entity-framework

我的代码运行良好:

//我的控制器

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
            };
        }




    }

并像这样使用它(控制器没有改变):

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)'方法,以及此方法   无法翻译成商店表达。

我知道我可以使用自动映射器。但是我真的很感兴趣使这项工作,并了解这里有什么问题。

3 个答案:

答案 0 :(得分: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;

首先需要调用数据库的原因是因为Entity Framework正在将LINQ代码转换为SQL代码,当它找到自定义Extension方法时,显然无法进行转换。

当您使用ToList()强制请求数据库时,您在C#代码中请求扩展方法,这显然是有效的。

答案 1 :(得分: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();

答案 2 :(得分:0)

您可以使用导航属性,如果它们已正确设置,并执行以下操作:

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

这样你也可以避免所有的映射。请注意使用导航属性的正确名称。

相关问题