如何使用 Linq to SQL C# 将普通对象转换为嵌套子对象

问题描述 投票:0回答:1

我正在处理一个应用程序,我从数据库中收到一个普通列表,我需要将其转换为以下 JSON 对象。到目前为止,这是我尝试过的。我不愿意使用嵌套的foreach循环。

JSON

{
  "Location": [
    {
      "LocationID": "123456",
      "DBSIdentifier": "EQUIP",
      "DBSVersion": "3221",
      "InterfaceVersion": "2.0",
      "LanguageCode": "EN",
      "CounterSale": [
        {
          "InvoiceNumber": "941041",
          "CreationTimestamp": "2018-04-02T07:03:18",
          "InvoiceTimestamp": "2018-04-02T07:03:18",
          "Part": [
            {
              "PartNumber": "AT194969",
              "Quantity": "1.00",
              "Description": "KEY",
              "DeerePart": "true",
              "MiscellaneousPart": "false",
              "PartsPerPackage": "1",
              "StockingLogicCode": "12A",
              "UnitofMeasure": "",
              "Warehouse": "D-1",
              "HistorySale": "N",
              "OnlineOrder": "",
              "PickListID": ""
            }
          ]
        }]
        }]
    }

代码

string connectionString = "data source=localhost;initial catalog=ASPENDV;integrated security=true;";
var result = new List<DataClass>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
    result = connection.Query<DataClass>("sp_TestData", commandType: System.Data.CommandType.StoredProcedure).ToList();
}


#region [@ ##### ]


var obj = result.GroupBy(x => x.LocationId);

var root = obj.Select(x => new Root()
{
    Location = x.Select(l => new Location()
    {
        LocationID = l.LocationId,
        DBSIdentifier = l.DBSIdentifier,
        CounterSale = x.GroupBy(x => x.InvoiceNumber).Select(c => new CounterSale()
        {
            InvoiceNumber = l.InvoiceNumber,
            CreationTimestamp = l.CreationTimestamp,
            Part = x.Select(p => new Part()
            {
                PartNumber = p.PartNumber,
                Description = p.Description,
            }).ToList()
        }).ToList(),
    }).ToList(),
}); ;

#endregion

模型

   public class DataClass
        {
            public string? LanguageCode { get; set; }
            public DateTime CreationTimestamp { get; set; }
            public string? DBSHEADERPARTSK { get; set; }
            public string? DBSIdentifier { get; set; }
            public int DBSVersion { get; set; }
            public string? Description { get; set; }
            public string? InvoiceNumber { get; set; }
            public Nullable<DateTime> InvoiceTimestamp { get; set; }
            public string? PartNumber { get; set; }
            public string? PartSerialNumber { get; set; }
            public int? PartPerPackage { get; set; }
            public int MfgId { get; set; }
            public int LocationId { get; set; }
        }

    public class CounterSale
    {
        public CounterSale()
        {
            this.Part = new List<Part>();
        }
        public string? InvoiceNumber { get; set; }
        public DateTime CreationTimestamp { get; set; }
        public DateTime InvoiceTimestamp { get; set; }
        public List<Part> Part { get; set; }
    }

    public class Location
    {
        public Location()
        {
            this.CounterSale = new List<CounterSale>();
        }
        public int LocationID { get; set; }
        public string? DBSIdentifier { get; set; }
        public string? DBSVersion { get; set; }
        public string? InterfaceVersion { get; set; }
        public string? LanguageCode { get; set; }
        public List<CounterSale> CounterSale { get; set; }
    }

    public class Part
    {
        public string? PartNumber { get; set; }
        public string? Quantity { get; set; }
        public string? Description { get; set; }
    }

    public class Root
    {
        public Root()
        {
            this.Location = new List<Location>();
        }
        public List<Location> Location { get; set; }
    }

我的存储过程返回我绑定到 DataClass 中的数据,我需要像 JSON 一样将其绑定到根模型中。

c# linq linq-to-sql
1个回答
0
投票

我建议通过首先按位置和发票分组然后仅按位置再次分组来自下而上构建嵌套分组。生成的结构将类似于您想要的结构,然后只需遍历分组即可构建最终的嵌套数据结构。

类似的东西(未经测试):

List<DataClass> result; // No initialization needed here
using (SqlConnection connection = new SqlConnection(connectionString))
{
    result = connection.Query<DataClass>("sp_TestData", commandType: System.Data.CommandType.StoredProcedure).ToList();
}

// Grouping<Key=LocationId, Collection=Grouping<Key={LocationId, InvoiceNumber}, Collection=DataClass>
var nestedGroups = result
    .GroupBy(dat => new {dat.LocationId, dat.InvoiceNumber})
    .GroupBy(invGroup => invGroup.Key.LocationId)
    //??maybe?? .ToList()
    ;

var root = new Root()
{
    Location = nestedGroups.Select(locGroup => new Location()
    {
        LocationID = locGroup.Key,
        DBSIdentifier = locGroup.First().First().DBSIdentifier,
        CounterSale = locGroup.Select(invGroup => new CounterSale()
        {
            InvoiceNumber = invGroup.Key.InvoiceNumber,
            CreationTimestamp = invGroup.First().CreationTimestamp,
            Part = invGroup.Select(dat => new Part()
            {
                PartNumber = dat.PartNumber,
                Description = dat.Description,
            }).ToList()
        }).ToList()
    }).ToList()
});

.First()
.First().First()
调用用于向下到达最低级别以检索不包含在上层分组键中的值。您可以在
DBSIdentifier
选择器中包含
CreationTimestamp
.GroupBy(...)
,但这可能会降低效率。

免责声明:我在脑海中输入了这个并且没有测试甚至语法检查这个。如果有错误请评论,我会更正(或者你可以自己更正)。我发布的内容完全行不通,也发表评论,我将删除答案。

© www.soinside.com 2019 - 2024. All rights reserved.