简体   繁体   中英

How to use Linq to create unique Collection which contains a collection

I am retrieving records from a db and creating the following object:

       public class RemittanceBatchProcessingModel
      {
            public string FileId { get; set; }
            public string SourceFileName { get; set; }
            public string BatchCode { get; set; }
            public string BatchType { get; set; }
            public decimal PaymentAmount { get; set; }
            public string BillingSystemCode { get; set; }
       }

Example objects created after db read:

FileId | SourceFileName | BatchCode | BatchType | PaymentAmt |BillingCode
    1  | test.file1.txt | 100       | S         | 1000.00    | Exc
    1  | test.file1.txt | 100       | S         | 2000.00    | Exc 
    1  | test.file1.txt | 200       | N         |  500.00    | Adc 
    2  | test.file2.txt | 300       | S         | 1200.00    | Exc 
    2  | test.file2.txt | 300       | S         | 1500.00    | Exc 

I want to create an object that has a collection of the unique files which has a collection of each summarized batch within a file. For example,

  Collection of Unique Files:
FileId | SourceFileName | BatchCode | BatchType | BatchTotal |RecordCount
    1  | test.file1.txt | 100       | S         | 3000.00    | 2
    1  | test.file1.txt | 200       | N         |  500.00    | 1
    2  | test.file2.txt | 100       | S         | 1700.00    | 2

I am able to create my collection of batches with no issue the problem I'm having is figuring out how to create the collection of unique files with the correct batches within them. I'm attempting this using the following:

    private static RemittanceCenterFilesSummaryListModel SummarizeFiles(RemittanceCenterSummaryListModel remittanceCenterSummaryListModel)
    {
       var summarizedBatches = SummarizeBatches(remittanceCenterSummaryListModel);

                   var fileResult = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord.GroupBy(x => new { x.FileId, x.SourceFileName })
            .Select(x => new RemitanceCenterFileSummarizedModel()
            {
                FileId = x.Key.FileId,
                SourceFileName = x.Key.SourceFileName,
                ScannedBatchCount = x.Count(y => y.BatchType == "S"),
                ScannedBatchAmount = x.Where(y => y.BatchType == "S").Sum(y => y.PaymentAmount),
                NonScannedBatchCount = x.Count(y => y.BatchType != "S"),
                NonScannedBatchAmount = x.Where(y => y.BatchType != "S").Sum(y => y.PaymentAmount),
            });

        var summaryListModel = CreateSummaryFilesListModel(fileResult);
        summaryListModel.Batches = summarizedBatches.RemittanceBatchSummary; 
        return summaryListModel;
    }
    private static RemittanceCenterFilesSummaryListModel CreateSummaryFilesListModel(IEnumerable<RemitanceCenterFileSummarizedModel> summaryModels)
    {
        var summaryModelList = new RemittanceCenterFilesSummaryListModel();

        foreach (var summaryFileRec in summaryModels)
        {
            var summaryModel = new RemitanceCenterFileSummarizedModel
            {
                FileId = summaryFileRec.FileId.ToString(CultureInfo.InvariantCulture),
                SourceFileName = summaryFileRec.SourceFileName.ToString(CultureInfo.InvariantCulture),
                ScannedBatchCount = summaryFileRec.ScannedBatchCount,
                ScannedBatchAmount = summaryFileRec.ScannedBatchAmount,
                NonScannedBatchCount = summaryFileRec.NonScannedBatchCount,
                NonScannedBatchAmount = summaryFileRec.NonScannedBatchAmount
            };

            summaryModelList.RemittanceFilesSummary.Add(summaryModel);
        }

        return summaryModelList;
    }

You can group it on the 4 columns including BatchType and BatchCode as well and pick the Count and sum the Amount like :

 var fileResult = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord
                     .GroupBy(x => new 
                                  { 
                                    x.FileId,
                                    x.SourceFileName,
                                    x.BatchType,
                                    x.BatchCode 
                                  })
                     .Select(x => new
                                 {
                                   FileId = x.Key.FileId,
                                   SourceFileName = x.Key.SourceFileName,
                                   BatchType = x.Key.BatchType,
                                   BatchCode = x.Key.BatchCode,
                                   BatchTotal= x.Sum(y=>y.PaymentAmt),
                                   RecordCount = x.Count()
                             });

I guess you need to GroupBy FileId & BatchType instead of FileName :-

var fileResult = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord
            .GroupBy(x => new { x.FileId, x.BatchType })
            .Select(x => 
            { 
                var firstObj = x.FirstOrDefault();
                return new RemitanceCenterFileSummarizedModel()
                { 
                   FileId = x.Key.FileId,
                   SourceFileName = firstObj.SourceFileName,
                   BatchCode = firstObj.BatchCode,
                   BatchType  = x.Key.BatchType,
                   BatchTotal  = x.Sum(z => z.PaymentAmt),
                   RecordCount = x.Count()
                };
            });

Considering FileId maps to SourceFileName & BatchCode maps to BatchType you can simply store the first set in a variable like I did in firstObj to get the relevant values which are not grouped. Please check for nulls before accessing relevant properties as it may cause NRE if no set is found.

For pure linq non fluent

 var files = new[] { 
                new { FileId = 1, SourceFileName =  "test.file1.txt" , BatchCode = 100 , BatchType = "S", PaymentAmt = 1000.00 , BillingCode = "Exc" },
                new { FileId = 1, SourceFileName =  "test.file1.txt" , BatchCode = 100 , BatchType = "S", PaymentAmt = 2000.00 , BillingCode = "Exc" },
                new { FileId = 1, SourceFileName =  "test.file1.txt" , BatchCode = 200 , BatchType = "N", PaymentAmt = 500.00 , BillingCode = "Adc" },
                new { FileId = 1, SourceFileName =  "test.file2.txt " , BatchCode = 300 , BatchType = "S", PaymentAmt = 1200.00 , BillingCode = "Exc" },
                new { FileId = 1, SourceFileName =  "test.file2.txt " , BatchCode = 300 , BatchType = "S", PaymentAmt = 1500.00 , BillingCode = "Exc" }
            };

            var result = from file in files
                         group file by new { file.FileId, file.BatchCode } into fileBachGroups
                         select new 
                         { 
                             FileId = 1, 
                             SourceFileName = fileBachGroups.First().SourceFileName, 
                             BatchCode = fileBachGroups.Key.BatchCode,
                             BatchType = fileBachGroups.First().BatchType,
                             BatchTotal = fileBachGroups.Sum(f => f.PaymentAmt),
                             RecordCount = fileBachGroups.Count()
                         };

            Console.WriteLine("FileId | SourceFileName | BatchCode | BatchType | BatchTotal |RecordCount");

            foreach (var item in result)
            {
                Console.WriteLine("{0} | {1} | {2} | {3} | {4} | {5}",item.FileId,item.SourceFileName, item.BatchCode, item.BatchType, item.BatchTotal, item.RecordCount);
            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM