C# 使用LINQ查询语法EF Core C的左外部联接#

C# 使用LINQ查询语法EF Core C的左外部联接#,c#,sql,entity-framework,linq,asp.net-core,C#,Sql,Entity Framework,Linq,Asp.net Core,我有一个关于以下内容的问题 未通过外键连接的两个表的左外连接 按第二个表中匹配的结果排序 我希望这是在LINQ查询方法语法中完成的,因为我正在根据随skip和limit一起提供的输入添加大量条件 如果我们有以下产品和最喜欢的表格 所以我想要的结果是: 这意味着收藏夹作为第一组的一部分,而不是收藏夹应该在它们后面。下面是我所做的尝试。 我能够连接表以获得输出,但不确定如何确保在第一页中获得所有FAV 这个答案与我的想法非常接近,但它得到了结果,然后进行排序,这在我的情况下是不可能的,因为我正

我有一个关于以下内容的问题

  • 未通过外键连接的两个表的左外连接
  • 按第二个表中匹配的结果排序
  • 我希望这是在LINQ查询方法语法中完成的,因为我正在根据随skip和limit一起提供的输入添加大量条件
  • 如果我们有以下产品和最喜欢的表格

    所以我想要的结果是:

    这意味着收藏夹作为第一组的一部分,而不是收藏夹应该在它们后面。下面是我所做的尝试。 我能够连接表以获得输出,但不确定如何确保在第一页中获得所有FAV

    这个答案与我的想法非常接近,但它得到了结果,然后进行排序,这在我的情况下是不可能的,因为我正在进行分页并使用iQueryEnable来获得更少的数据

    开放的任何解决方案,以实现同样的目标

    [Table("Product")]
    public class ProductModel
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Guid ProductId { get; set; }
        public string ProductName {get; set;}
        public bool IsFavorite { get; set; }
    }
    
    [Table("UserFavorite")]
    public class UserFavoriteModel
    {
        [Required]
        public Guid UserId { get; set; }
        [Required]
        public Guid Identifier { get; set; }
        [Required]
        public FavoriteType Type { get; set; }
    }
    
    // Gets products
    private async Task<List<ProductModel>> GetProductsAsync(
        Guid categoryId, 
        Guid subCategoryId, 
        int from,
        int limit)
    {
        var query = _context.Products.AsQueryable();
    
        if (!string.IsNullOrEmpty(categoryId))
            query = query.Where(product => product.CategoryId == categoryId);
        if (!string.IsNullOrEmpty(subCategoryId))
            query = query.Where(product => product.SubCategoryId == subCategoryId);
    
        query = query.Skip(from).Take(limit);
    
        var products = await query.ToListAsync();
    
        query = query.GroupJoin(
        _context.Favorites.AsNoTracking()
        .Where(favorite => favorite.Type == FavoriteType.FASHION)
        // This user Id will come from context just adding for overall picture.
        .Where(favorite => favorite.UserId == userId),
        //This orderby if I add will not make any difference.
        //.OrderByDescending(favorite => favorite.Identifier),
        v => v.ProductId,
        f => f.Identifier,
        (product, fav) => new { product, fav }).
        SelectMany(x => x.Fav.DefaultIfEmpty(),
                        (x, y) => SetFavorite(x.Project, y));
    
    }
    
    private static ProductModel SetFavorite(ProductModel v, UserFavoriteModel si)
    {
        v.IsFavorite = (si != null);
        return v;
    }
    
    [表格(“产品”)]
    公共类产品模型
    {
    [关键]
    [数据库生成(DatabaseGeneratedOption.Identity)]
    公共Guid ProductId{get;set;}
    公共字符串ProductName{get;set;}
    公共bool是收藏夹{get;set;}
    }
    [表格(“用户收藏夹”)]
    公共类UserFavoriteModel
    {
    [必需]
    公共Guid用户标识{get;set;}
    [必需]
    公共Guid标识符{get;set;}
    [必需]
    公共FavoriteType类型{get;set;}
    }
    //获取产品
    专用异步任务GetProductsAsync(
    Guid类别ID,
    Guid子类别ID,
    int from,
    整数限制)
    {
    var query=_context.Products.AsQueryable();
    如果(!string.IsNullOrEmpty(categoryId))
    query=query.Where(product=>product.CategoryId==CategoryId);
    如果(!string.IsNullOrEmpty(子类别ID))
    query=query.Where(product=>product.SubCategoryId==SubCategoryId);
    query=query.Skip(from).Take(limit);
    var products=await query.ToListAsync();
    query=query.GroupJoin(
    _context.Favorites.AsNoTracking()
    .Where(favorite=>favorite.Type==FavoriteType.FASHION)
    //此用户Id将来自上下文,仅用于添加整体图片。
    .Where(favorite=>favorite.UserId==UserId),
    //如果我添加此orderby,将不会产生任何影响。
    //.OrderByDescending(收藏夹=>favorite.Identifier),
    v=>v.ProductId,
    f=>f.标识符,
    (产品,fav)=>新{产品,fav})。
    选择many(x=>x.Fav.DefaultIfEmpty(),
    (x,y)=>SetFavorite(x.Project,y));
    }
    私有静态ProductModel SetFavorite(ProductModel v,UserFavoriteModel si)
    {
    v、 IsFavorite=(si!=null);
    返回v;
    }
    
    我会这样做:

    var query =
       _context.Products.AsQueryable().Select(p => new ProductModel {
          ProductId = p.ProductId,
          ProductName = p.ProductName,
          IsFavorite =
             _context.Favorites.Any(f =>
                f.Identifier = p.ProductId &&
                f.Type == FavoriteType.FASHION &&
                f.UserId == userId
             )
       }).OrderByDescending(favorite => favorite.Identifier);
    

    AsNoTracking内部投影,没有返回记录-这对我来说是新事物;)@阿杜奇,非常感谢。这看起来比我想象的要简单,要学的东西很多:)。有一些打字错误可能对其他人有用f.Identifier=p.ProductId(应该有==),并且顺序应该是OrderByDescending(favorite=>favorite.IsFavorite)。如果我在ProductModel中有大量字段,我有一个小小的澄清,那就是有没有一种方法可以简化它,而不是在select中声明所有字段。我尝试了选择(p=>{p.IsFavorite=favs condition here;return p;}),但我认为表达式中不支持该选项。@SvyatoslavDanyliv我只是将此方法发布到SO中,但忘记添加返回部分:)。据我所知,AsNoTracking仅用于读取,我甚至将其用于_context.Products.AsNoTracking,是否有我不应该使用的原因。这是因为IQueryable?
    AsNoTracking
    用于“通知”ChangeTracker不注册加载的实体。如果您没有获得记录,只需
    计数
    任何
    ,等等-因此没有任何更改跟踪。