[英]From Linq To List Using Extension Method
I have this code that runs fine: 我有运行良好的代码:
// my controller //我的控制器
public HttpResponseMessage GetUserFavorites(string id)
{
var response = Request.CreateResponse();
response.Content = new StringContent(JsonConvert.SerializeObject(jobRepository.GetUserFavorites(id)));
response.StatusCode = HttpStatusCode.OK;
return response;
}
// my jobRepository //我的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;
}
The issue is, that the mapping to ProfileInfo
will return in many places in my code. 问题是,到
ProfileInfo
的映射将在我的代码的许多地方返回。 I obviously want to avoid that. 我显然想避免这种情况。 I thought of using extension method, that will map from EF to my class like this:
我想到使用扩展方法,它将像这样从EF映射到我的班级:
// my extension: //我的扩展名:
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
};
}
}
and use it like this (controler is not changed): 并像这样使用它(控制器不变):
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;
}
It is compiled OK, but I got this error in run time: 它已编译正常,但在运行时出现此错误:
An exception of type 'System.NotSupportedException' occurred in
Newtonsoft.Json.dll
but was not handled in user codeNewtonsoft.Json.dll
发生类型'System.NotSupportedException'的异常,但未在用户代码中处理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.附加信息:
LINQ
to Entities无法识别方法'myApp.Models.InfoClass.ProfileInfo ToProfileInfo(myApp.Models.TB_Res_Profile)'方法,并且该方法无法转换为商店表达式。
I know there are auto mappers that I can use. 我知道我可以使用自动映射器。 but it really interest me to make this work, and understand what is wrong here.
但是让我真正感兴趣的是完成这项工作,并了解这里有什么问题。
You can make it work using extension method if you first force a call to a database using for example ToList()
and then use a mapper: 如果首先使用例如
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;
The reason why you need to make a call to a database first, is because Entity Framework is making a translation of your LINQ code to SQL code, and when it finds custom Extension method it obviously cannot make a translation. 之所以需要首先调用数据库,是因为Entity Framework正在将LINQ代码转换为SQL代码,并且当它找到自定义的Extension方法时,显然不能进行转换。
When you force a request to database using ToList()
you make a request to extension method in C# code, which is obviously valid thing to do. 当您使用
ToList()
强制对数据库的请求时,您会使用C#代码向扩展方法发出请求,这显然是正确的做法。
You should pass the whole IQueryable
and return another IQueryable
. 您应该传递整个
IQueryable
并返回另一个IQueryable
。 Something like this: 像这样:
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
});
}
Now you only have Expression trees, which EF will be pleased to work with: 现在,您只有表达式树,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();
You could use the navigation properties , if they're properly set in place, and do something like this: 如果正确设置了导航属性,则可以使用它们,然后执行以下操作:
from p in db.TB_Res_Profile
where p.TB_Res_Favorite.UserId == iUserId select p;
This way you'll also avoid all that mapping. 这样,您还可以避免所有映射。 Mind using the correct name for the navigation property.
请注意使用导航属性的正确名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.