过滤大于或等于 LINQ 表达式错误的结果

Filter greater or equal results in LINQ expression error

我正在我的 .netcore 项目中实施 OData,我正在尝试应用一些过滤器。当我使用odata/productshops?$filter=SellingPrice eq 20时,我得到了售价为20的产品。

但是当我尝试过滤所有售价大于或等于 20 的产品时: odata/productshops?$filter=SellingPrice ge 20

我收到内部服务器错误消息:

The LINQ expression 'DbSet<ProductShop>
    .Where(p => p.SellingPrice >= __TypedProperty_0)' could not be translated. 
Either rewrite the query in a form that can be translated, or switch 
to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().

我虽然它必须对十进制的字段类型做一些事情,所以我尝试写 20.020M20.0M,但结果仍然相同我不知道为什么它会给我这个错误。

如何正确过滤大于或等于

我的启动配置:

var builder = new ODataConventionModelBuilder(app.ApplicationServices);
builder.EntitySet<ProductShopOData>("ProductShops");

app.UseMvc(routerBuilder =>
{
    routerBuilder.Select().Expand().Filter().OrderBy().MaxTop(100).Count();
    routerBuilder.MapODataServiceRoute("ODataRoute", "odata", builder.GetEdmModel());
});

控制器:

[ODataRoutePrefix("Productshops")]
[Authorize]
public class ProductShopsController : ODataController
{
    private readonly MapperConfiguration _config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<ProductShop, ProductShopOData>();
    });

    private readonly Context _context;

    public ProductShopsController(Context context)
    {
        _context = context;
    }

    [EnableQuery]
    [ODataRoute]
    [HttpGet]
    public IQueryable<ProductShopOData> GetProductShop()
    {
        return _context.ProductShops
            .ProjectTo<ProductShopOData>(_config);
    }
}

使用的实体:

[Table("pro_product_shop_bind")]
public class ProductShop
{
    [Column("id")]
    [Key]
    public int Id { get; set; }

    [Column("status")]
    [Required]
    public RecordStatus Status { get; set; } = RecordStatus.Valid;
    
    [Column("shop_id")]
    [ForeignKey("Shop")]
    [Required]
    public int ShopId { get; set; }
    
    [Column("product_id")]
    [ForeignKey("Product")]
    [Required]
    public int ProductId { get; set; }
    
    [Column("type_code")]
    [Required]
    public ProductShopBindType TypeCode { get; set; }
    
    [Column("request_date")]
    public DateTime? RequestDate { get; set; }
    
    [Column("approval_date")]
    public DateTime? ApprovalDate { get; set; }
    
    [Column("request_status_code")]
    [Required]
    public RequestStatus RequestStatusCode { get; set; }

    [Column("is_hidden")]
    [Required]
    public bool IsHidden { get; set; } = true;

    [Column("is_automatic")]
    [Required]
    public bool IsAutomatic { get; set; } = true;
    
    [Column("delivery_status_id")]
    [ForeignKey("DeliveryStatus")]
    public int? DeliveryStatusId { get; set; }
    
    [Column("status_limit")]
    public short? StatusLimit { get; set; }
    
    [Column("below_limit_status_id")]
    [ForeignKey("BelowLimitStatus")]
    public int? BelowLimitStatusId { get; set; }
    
    [Column("above_limit_status_id")]
    [ForeignKey("AboveLimitStatus")]
    public int? AboveLimitStatusId { get; set; }
    
    [Column("zero_limit_status_id")]
    [ForeignKey("ZeroLimitStatus")]
    public int? ZeroLimitStatusId { get; set; }
    
    [Column("label_id")]
    [ForeignKey("Label")]
    public int? LabelId { get; set; }
    
    [Column("category_id")]
    [ForeignKey("Category")]
    public int? CategoryId { get; set; }
    
    [Column("warranty_id")]
    [ForeignKey("Warranty")]
    public int? WarrantyId { get; set; }
    
    [Column("selling_price", TypeName = "decimal(10,2)")]
    [Required]
    public decimal SellingPrice { get; set; }
    
    [Column("other_price", TypeName = "decimal(10,2)")]
    [Required]
    public decimal OtherPrice { get; set; }

    [Column("use_default_price")]
    [Required]
    public bool UseDefaultPrice { get; set; } = true;

    [Column("price_changed")]
    [Required]
    public bool PriceChanged { get; set; } = false;
    
    [Column("shipper_id")]
    public int? ShipperId { get; set; }
    
    [Column("vat_type")]
    [Required]
    public VatType VatType { get; set; }

    [Column("must_be_stored")] 
    [Required] 
    public bool MustBeStored { get; set; } = true;

    public virtual Shop Shop { get; set; }
    public virtual Product Product { get; set; }
    public virtual DeliveryTime DeliveryStatus { get; set; }
    public virtual DeliveryTime BelowLimitStatus { get; set; }
    public virtual DeliveryTime AboveLimitStatus { get; set; }
    public virtual DeliveryTime ZeroLimitStatus { get; set; }
    public virtual Label Label { get; set; }
    public virtual Category Category { get; set; }
    public virtual Warranty Warranty { get; set; }
}

EF Core 版本为 3.1.9。

更新:

找到了某种“解决方案” here,但有 .ToList() 的解决方法,其中获取内存中的所有内容并将其转换为 AsQueryable( ).但这不是最优的,如何正确地实现它?

这很可能是由于向数据库发送了错误的查询造成的。 我猜你是在查询方法之外计算 SellingPrice,这就是导致问题的原因。

(我会 post 这作为评论,但我仍然没有足够的声誉 - 抱歉!)

这可能是 .NETcore 版本的错误,在新的 .NET 5 中一切正常。