使用扩展方法从 Linq 到列表

From Linq To List Using Extension Method

我有这段代码运行没问题:

// 我的控制器

public HttpResponseMessage GetUserFavorites(string id)
{

    var response = Request.CreateResponse();

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

    return response;

}

// 我的作业库

     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 的映射将在我的代码中的许多地方 return。我显然想避免这种情况。我想到了使用扩展方法,它将像这样从 EF 映射到我的 class:

// 我的分机:

 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;


}

编译成功,但我在 运行 时间得到了这个错误:

An exception of type 'System.NotSupportedException' occurred in Newtonsoft.Json.dll but was not handled in user code

Additional information: LINQ to Entities does not recognize the method 'myApp.Models.InfoClass.ProfileInfo ToProfileInfo(myApp.Models.TB_Res_Profile)' method, and this method cannot be translated into a store expression.

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

如果您首先使用 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 代码,当它找到自定义扩展方法时显然不能翻译。

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

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

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

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

你应该通过整个 IQueryable 和 return 另一个 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();