2 Câu hỏi: Linq GroupBy khoản không bao gồm các mục có số không

câu hỏi được tạo ra tại Wed, May 8, 2019 12:00 AM

Tôi có một truy vấn bên dưới được cho là nhóm kết quả theo Id, EntityName, DocType, Thẩm quyền. Đối với mỗi nhóm, truy vấn cũng trả về các mục ProductList.

Hiện tại nếu nhóm có chứa một hoặc nhiều sản phẩm, thì tôi có thể thấy kết quả đưa ra một nhóm có sự kết hợp của Id, EntityName, DocType, Thẩm quyền và Danh sách sản phẩm, tuy nhiên nếu kết quả không chứa sản phẩm cho một nhóm cụ thể tôi không thấy nhóm nào cả. Những gì tôi muốn làm là hiển thị các nhóm ngay cả khi không có bất kỳ sản phẩm nào trong nhóm. Vì vậy, nếu số lượng ProductList bằng 0, tôi muốn đặt       ProductList = Danh sách mới NettingAgribution ProducttDto. Bất kỳ đầu vào sẽ được đánh giá cao.

          var result = from nae in nettingAgreementEntities.Result
                     join no in nettingOpinions.Result 
                          on nae.EntityId equals no.EntityId 
                     join np in nettingProducts.Result 
                          on no.ProductId equals np.Id
                     group np by new 
                               { nae.EntityId, 
                                 nae.EntityName, 
                                 nae.DocType,
                                 nae.Jurisdiction 
                               } into g                      
                     select new NettingAgreementEntityDto
                     {
                         Id = g.Key.EntityId,
                         EntityName = g.Key.EntityName,
                         DocType = g.Key.DocType,
                         Jurisdiction = g.Key.Jurisdiction,
                         ProductList =  g.Select(x => new                                            
                                        NettingAgreementProductDto
                                        {
                                           Id = x.Id,
                                           Name = x.Name
                                        }).ToList()
                     };
    
2
  1. Không phải là nae.EntityId duy nhất trong nettingAgreementEntities.Result? Điều này nghe có vẻ giống như ứng cử viên cho Tham gia được nhóm chứ không phải (bên trong) Join + GroupBy. Hiện tại Tham gia bên trong đang lọc truy vấn của bạn,
    2019-05-09 08: 24: 19Z
  2. Xin chào @IvanStoev Bạn có nói chừng nào tôi có nae.EntityId trong phần tham gia bên trong tôi sẽ không bao giờ nhận được kết quả tôi muốn?
    2019-05-09 08: 35: 28Z
  3. Không. Tôi đang nói rằng truy vấn hiện tại của bạn chứa 2 liên kết bên trong, sẽ lọc nae mà không cần nono mà không cần np. Trong khi GroupJoin
    2019-05-09 08: 39: 45Z
  4. Xin chào @IvanStoev tôi đã mô phỏng một truy vấn dựa trên đề xuất của bạn. Nếu tôi gửi câu hỏi của tôi như là một câu trả lời, bạn có thể sửa nó không? nó sẽ nổ tung khi tôi cố gắng tham gia bên ngoài bên trái.
    2019-05-09 09: 34: 51Z
  5. Chắc chắn .. Nhưng tôi sẽ cần các lớp thực thể /dto liên quan. Và định nghĩa của nettingAgreementEntities.Result, nettingOpinions.ResultnettingProducts.Result - đây là những IQueryable từ EF, v.v.
    2019-05-09 10: 18: 46Z
  6. 2 Câu trả lời                              2                         

    Để tóm tắt lại từ các nhận xét, hiện tại truy vấn của bạn đang sử dụng Tham gia nội bộ để liên kết NettingAgreementEntity với NettingAgreementProducts. Điều này không chỉ nhân bộ kết quả (và do đó yêu cầu bạn sử dụng GroupBy sau), mà còn lọc ra NettingAgreementEntity mà không cần NettingAgreementProducts.

    Bạn có thể đạt được mục tiêu bằng cách chuyển sang Tham gia nhóm (hoặc Bên ngoài bên ngoài Tham gia + GroupBy).

    Nhưng tại sao nhập tất cả các biến chứng này. Các thuộc tính điều hướng của EF cho phép bạn gần như quên đi các phép nối thủ công và cũng cho phép bạn dễ dàng xem bội số, do đó bạn có cần nhóm kết quả hay không.

    Vì vậy, những gì tôi muốn đề xuất là thêm thuộc tính điều hướng bộ sưu tập hiện đang thiếu vào lớp NettingAgreementEntity của bạn:

    public class NettingAgreementEntity
    {
        // ...
        public virtual ICollection<NettingOpinion> Opinions { get; set; }
    }
    

    Tùy chọn làm tương tự cho NettingAgreementProduct trong trường hợp trong tương lai bạn cần một cái gì đó tương tự cho các sản phẩm (đó là mối quan hệ nhiều-nhiều và có thể được truy vấn từ cả hai bên).

    Ngoài ra, tôi sẽ đổi tên các thuộc tính điều hướng lớp NettingOpinion NettingAgreementProductNavigationNettingAgreementEntityNavigation ngắn hơn, ví dụ ProductEntity. Những tên này (cũng như tên của các thuộc tính điều hướng bộ sưu tập) không ảnh hưởng đến lược đồ cơ sở dữ liệu, nhưng IMHO cung cấp khả năng đọc tốt hơn.

    Khi bạn đã có điều đó, bạn sẽ thấy rằng truy vấn LINQ mong muốn là vấn đề đơn giản Select chuyển đổi lớp thực thể thành DTO và để trình dịch truy vấn EF tạo ra các phép nối cần thiết cho bạn:

    var result = db.Set<NettingAgreementEntity>()
        .Selec(nae => new NettingAgreementEntityDto
        {
            Id = nae.EntityId,
            EntityName = nae.EntityName,
            DocType = nae.DocType,
            Jurisdiction = nae.Jurisdiction,
            ProductList = nae.Opinions
                .Select(no => new NettingAgreementProductDto
                {
                    no.Product.Id,
                    no.Product.Name,
                }).ToList(),
        });
    
        
    2
    2019-05-09 12: 51: 29Z
    1. Cảm ơn bạn đã giúp đỡ. Tôi đã cập nhật câu trả lời của mình (truy vấn cuối cùng) dựa trên đề xuất của bạn và hiện tại nó đang hoạt động.
      2019-05-09 21: 16: 21Z

    Dưới đây là những gì tôi đã cố gắng cho đến nay. Tôi tin rằng truy vấn không hoàn toàn chính xác ở giai đoạn này vì nó vẫn bỏ qua các nhóm không có sản phẩm.

    Thực thể NettingOpinion

    [Table("NettingOpinion",Schema = "dbo")]
    public class NettingOpinion
    {
        [Key]
        [Column("NettingOpinionID")]
        public int NettingOpinionId { get; set; }
    
        [Column("ProductID")]
        public int ProductId { get; set; }
    
        [Column("EntityID")]
        public int EntityId { get; set; }
    
        [ForeignKey("ProductId")]
        public virtual  NettingAgreementProduct NettingAgreementProductNavigation { get; set; }
    
        [ForeignKey("EntityId")]
        public virtual  NettingAgreementEntity NettingAgreementEntityNavigation { get; set; }
    }  
    

    Thực thể sản phẩm NettAgribution

        public  class NettingAgreementProduct
        {
            public NettingAgreementProduct()
            {
                NettingAgreementDefaults = new HashSet<NettingAgreementDefaults>();
            }
    
            [Column("ProductID")]
            [DatabaseGenerated(DatabaseGeneratedOption.None)]
            public int Id { get; set; }
    
            [Required]
            [Column("ProductName")]
            [StringLength(255)]
            public string Name { get; set; }
    
            public virtual ICollection<NettingAgreementDefaults> NettingAgreementDefaults { get; set; }
        }
    

    NettingAgributionEntity

    [Table("NettingAgreementEntity")]
    public class NettingAgreementEntity
    {
        [Key]
        [Column("EntityID")]
        public int EntityId { get; set; }
    
        [MaxLength(50,ErrorMessage = "DocType Cannot be more than 50 characters")]
        [Required]
        public string DocType { get; set; }
    
    
        [Column("Jurisdiction")]
        [MaxLength(2, ErrorMessage = "Jurisdiction Cannot have more than two characters")]
        [Required]
        public string Jurisdiction { get; set; }
    
        [MaxLength(255,ErrorMessage = "EntityName Cannot have more than 255 characters")]
        [Required]
        public string EntityName { get; set; }
    
        [ForeignKey("DocType")]
        public virtual  DocType DocTypeNavigation { get; set; }
    
    }
    

    Truy vấn thực tế

                         var result = from nae in nettingAgreement
                         join no in nettingOpinion on nae.EntityId equals no.EntityId into pp
                         from test in pp.DefaultIfEmpty(new NettingOpinion())
                         join np in nettingProduct on test.ProductId equals np.Id into npd
                         from npdSubset in npd.DefaultIfEmpty()
                         group npdSubset by new { nae.EntityId, nae.EntityName, nae.DocType, nae.Jurisdiction } into g
                         select new NettingAgreementEntityDto
                         {
                             Id = g.Key.EntityId,
                             EntityName = g.Key.EntityName,
                             DocType = g.Key.DocType,
                             Jurisdiction = g.Key.Jurisdiction,
                             ProductList =  g.Select(x => new NettingAgreementProductDto
                             {
                                 Id = x?.Id ?? 0,
                                 Name = x == null ? string.Empty : x.Name
                             }).ToList()
                         };
    
        
    0
    2019-05-09 21: 15: 52Z
    1. Dựa trên đề xuất của @Ivan Stoev, tôi đã cập nhật câu trả lời của mình (truy vấn cuối cùng) hiện đang hoạt động.
      2019-05-09 21: 17: 58Z
nguồn đặt đây