使用扩展方法从 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();
我有这段代码运行没问题:
// 我的控制器
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 codeAdditional 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();