实体框架无法翻译以进行过滤

发布于 2025-02-10 11:24:23 字数 3619 浏览 4 评论 0原文

我在编写使用过滤器过滤产品的查询时遇到了问题。我希望能够通过productFilter过滤,但是我得到了

无法翻译。可以通过插入“可忽略的”,“ asasyncenumerable”,“ tolist”或“ tolistAsync'的呼叫来重写可以翻译的形式的查询,或者明确切换到客户端评估。

    public class ProductFilter
    {
        public DateTime? AvailableFrom { get; set; }
        public DateTime? AvailableTo { get; set; }
        public Size? Size { get; set; }
        public int? RangeFrom { get; set; }
        public int? RangeTo { get; set; }
        public List<Facet>? Facets { get; set; }
    }

    public class Facet
    {
        public Guid Id { get; set; }
        public List<FacetValue> FacetValues { get; set; } = new List<FacetValue>();
    }

    public class FacetValue
    {
        public Guid Id { get; set; }
    }
public class Product : EntityBase
{
    public virtual ICollection<ProductVariant>? Variants { get; set; }
    public virtual ICollection<FacetValue> FacetValues { get; set; } = new List<FacetValue>();
}

public class ProductVariant : EntityBase
{
    public Guid ProductId { get; set; }
    public virtual Product Product { get; set; } = null!;

    public Size Size { get; set; }
    public virtual ICollection<Order> Orders { get; set; } = new List<Order>();
    public virtual ICollection<FacetValue> FacetValues { get; set; } = new List<FacetValue>();
}

public class FacetValue : EntityBase
{
    public string Name { get; set; } = null!;

    public Guid FacetId { get; set; }
    public virtual Facet Facet { get; set; } = null!;
    
    public virtual ICollection<ProductVariant> ProductVariants { get; set; } = new List<ProductVariant>();
    public virtual ICollection<Product> Products { get; set; } = new List<Product>();
}

public class Facet : EntityBase
{
    public string Name { get; set; } = null!;
    public virtual ICollection<FacetValue> Values { get; set; } = new List<FacetValue>();
}
      return productsQuery
                        .Where(p =>
                            p.Variants != null && p.Variants!.Any(pv =>
                                !pv.Orders.Any(o =>
                                    o.StartDate <= requestFilter.AvailableTo ||
                                    o.EndDate <= requestFilter.AvailableTo
                                )
                                &&
                                (requestFilter.Size == null || pv.Size == requestFilter.Size)
                                && pv.State == ProductVariantState.Active
                                &&
                                (
                                    requestFilter.Facets.IsNullOrEmpty() ||
                                    requestFilter.Facets!.All(
                                        filterFacet =>
                                            filterFacet.FacetValues
                                                .Any(filterFacetValue =>
                                                    p.FacetValues.Any(fv => fv.Id == filterFacetValue.Id))
                                            ||
                                            filterFacet.FacetValues
                                                .Any(filterFacetValue =>
                                                    pv.FacetValues.Any(fv => fv.Id == filterFacetValue.Id))
                                    )
                                )
                            )
                        );

I'm having a problem with writing a query for filtering products with a filter. I would like to be able to filter by a ProductFilter but I'm getting

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 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.

    public class ProductFilter
    {
        public DateTime? AvailableFrom { get; set; }
        public DateTime? AvailableTo { get; set; }
        public Size? Size { get; set; }
        public int? RangeFrom { get; set; }
        public int? RangeTo { get; set; }
        public List<Facet>? Facets { get; set; }
    }

    public class Facet
    {
        public Guid Id { get; set; }
        public List<FacetValue> FacetValues { get; set; } = new List<FacetValue>();
    }

    public class FacetValue
    {
        public Guid Id { get; set; }
    }
public class Product : EntityBase
{
    public virtual ICollection<ProductVariant>? Variants { get; set; }
    public virtual ICollection<FacetValue> FacetValues { get; set; } = new List<FacetValue>();
}

public class ProductVariant : EntityBase
{
    public Guid ProductId { get; set; }
    public virtual Product Product { get; set; } = null!;

    public Size Size { get; set; }
    public virtual ICollection<Order> Orders { get; set; } = new List<Order>();
    public virtual ICollection<FacetValue> FacetValues { get; set; } = new List<FacetValue>();
}

public class FacetValue : EntityBase
{
    public string Name { get; set; } = null!;

    public Guid FacetId { get; set; }
    public virtual Facet Facet { get; set; } = null!;
    
    public virtual ICollection<ProductVariant> ProductVariants { get; set; } = new List<ProductVariant>();
    public virtual ICollection<Product> Products { get; set; } = new List<Product>();
}

public class Facet : EntityBase
{
    public string Name { get; set; } = null!;
    public virtual ICollection<FacetValue> Values { get; set; } = new List<FacetValue>();
}
      return productsQuery
                        .Where(p =>
                            p.Variants != null && p.Variants!.Any(pv =>
                                !pv.Orders.Any(o =>
                                    o.StartDate <= requestFilter.AvailableTo ||
                                    o.EndDate <= requestFilter.AvailableTo
                                )
                                &&
                                (requestFilter.Size == null || pv.Size == requestFilter.Size)
                                && pv.State == ProductVariantState.Active
                                &&
                                (
                                    requestFilter.Facets.IsNullOrEmpty() ||
                                    requestFilter.Facets!.All(
                                        filterFacet =>
                                            filterFacet.FacetValues
                                                .Any(filterFacetValue =>
                                                    p.FacetValues.Any(fv => fv.Id == filterFacetValue.Id))
                                            ||
                                            filterFacet.FacetValues
                                                .Any(filterFacetValue =>
                                                    pv.FacetValues.Any(fv => fv.Id == filterFacetValue.Id))
                                    )
                                )
                            )
                        );

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

本宫微胖 2025-02-17 11:24:23

答案实际上很简单。

        if (!requestFilter.Facets.IsNullOrEmpty())
        {
            foreach (var filterFacet in requestFilter.Facets!)
            {
                productsQuery = productsQuery
                    .Where(p =>
                        p.Variants != null && p.Variants!.Any(pv =>
                            (requestFilter.Size == null || pv.Size == requestFilter.Size) &&
                            pv.State == ProductVariantState.Active &&
                            (
                                p.FacetValues.Any(
                                    pFv => filterFacet.FacetValues.Select(fv => fv.Id).Contains(pFv.Id)
                                )
                                ||
                                pv.FacetValues.Any(
                                    pvFv => filterFacet.FacetValues.Select(fv => fv.Id).Contains(pvFv.Id)
                                )
                            )
                        )
                    );
            }
        }

但是我想知道如何重构代码以使其更有用并提取以下内容:


!pv.Orders.Any(o =>
    o.StartDate <= requestFilter.AvailableTo ||
    o.EndDate <= requestFilter.AvailableTo)

The answer was actually pretty straightforward.

        if (!requestFilter.Facets.IsNullOrEmpty())
        {
            foreach (var filterFacet in requestFilter.Facets!)
            {
                productsQuery = productsQuery
                    .Where(p =>
                        p.Variants != null && p.Variants!.Any(pv =>
                            (requestFilter.Size == null || pv.Size == requestFilter.Size) &&
                            pv.State == ProductVariantState.Active &&
                            (
                                p.FacetValues.Any(
                                    pFv => filterFacet.FacetValues.Select(fv => fv.Id).Contains(pFv.Id)
                                )
                                ||
                                pv.FacetValues.Any(
                                    pvFv => filterFacet.FacetValues.Select(fv => fv.Id).Contains(pvFv.Id)
                                )
                            )
                        )
                    );
            }
        }

But I'm wondering how I could refactor the code to make it more usable and extract for instance the bit below:


!pv.Orders.Any(o =>
    o.StartDate <= requestFilter.AvailableTo ||
    o.EndDate <= requestFilter.AvailableTo)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文