我的代码运行良好:
//我的控制器
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)'方法,以及此方法 无法翻译成商店表达。
我知道我可以使用自动映射器。但是我真的很感兴趣使这项工作,并了解这里有什么问题。
答案 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;
这样你也可以避免所有的映射。请注意使用导航属性的正确名称。