问题描述
当我尝试在 where 子句中使用 props.getValue 方法时,出现错误。出现这个错误是因为LINQ无法在sql中翻译这个方法的调用,因为sql不知道这个方法。我读过一些关于表达式树的内容,但我不太明白如何使用它们,所以如果有人能解释我如何正确使用它们就太好了。
我的控制器方法:
int end = pageNumber * filter; int start = end - filter;
var query = GetRequestsWithoutFilter().Where(r => r.RequestStatus == 1);
if (attribute != null && title!=null)
{
if (attribute.Equals("movieReleaseDate"))
{
int i = Int32.Parse(title);
query = query.Where(r => (r.Movie.MovieReleaseDate) == i);
}
else
{
Movie m = new Movie();
PropertyInfo props = m.GetType().GetProperties().Where(p => String.Equals(attribute,p.Name,StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
if (props!=null)
{
query = query.Where(r => ((string)props.GetValue(r.Movie)).Substring(0,(title.Length < r.Movie.MovieTitle.Length ? title.Length : r.Movie.MovieTitle.Length)).toupper().Equals(title));
}
}
}
try {
var result = await query.Skip(start).Take(filter).ToListAsync();
if (result == null)
{
return NotFound();
}
return result;
} catch(Exception e)
{
return null;
}
}
GetRequestsWithoutFilter:
[NonAction]
private IQueryable<Request> GetRequestsWithoutFilter()
{
IQueryable<Request> query = _context.Requests.Include(r => r.User)
.Include(r => r.Movie)
.Select(e => new Request()
{
RequestID = e.RequestID,MovieID = e.MovieID,Movie = new Movie()
{
MovieID = e.MovieID,MovieTitle = e.Movie.MovieTitle,MovieDescription = e.Movie.MovieDescription,MovieDirector = e.Movie.MovieDirector,MovieProducer = e.Movie.MovieProducer,ImageSrc = String.Format("{0}://{1}{2}/Images/Movies/{3}",Request.Scheme,Request.Host,Request.PathBase,e.Movie.ImageName),MovieReleaseDate = e.Movie.MovieReleaseDate,},UserID = e.UserID,User = new User()
{
UserID = e.User.UserID,UserVorname = e.User.UserVorname,UserNachname = e.User.UserNachname
},RequestDate = e.RequestDate,RequestStatus = e.RequestStatus
});
return query;
}
电影模型:
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace MoviesWebApi.Models
{
public class Movie
{
public Movie()
{
Requests = new HashSet<Request>();
}
[Key]
public int MovieID { get; set; }
[Column(TypeName = "nvarchar(40)")]
public string MovieTitle { get; set; }
[Column(TypeName = "nvarchar(1000)")]
public string MovieDescription { get; set; }
[Column(TypeName = "nvarchar(40)")]
public string MovieDirector { get; set; }
[Column(TypeName = "nvarchar(40)")]
public string MovieProducer { get; set; }
public int MovieReleaseDate { get; set; }
[Column(TypeName = "nvarchar(100)")]
public string ImageName { get; set; }
[NotMapped]
public IFormFile ImageFile { get; set; }
[NotMapped]
public string ImageSrc { get; set; }
public ICollection<Request> Requests { get; set; }
}
}
解决方法
像这样的反射调用
((string)props.GetValue(r.Movie))
作为查询表达式树的一部分不可翻译。
您在此处获得的是检索属性的值。与它等价的表达式是 Expression.Property
,但是您需要使用 Expression
类方法构造整个谓词,这既乏味又容易出错,或者使用一些辅助实用程序来组合表达式。>
这并不难,但在 EF Core 中有一个更简单的解决方案,因为它提供了一种称为 EF.Property
的特殊方法,它可以被识别并正确翻译。
为了使用它,您只需要知道属性名称和类型。后者在动态场景中有点问题,但幸运的是您似乎针对 string
类型属性,因此只需将上面的替换为
EF.Property<string>(r.Movie,props.Name)