【问题标题】:c# linq-to-sql EF query to match a particular JSON structurec# linq-to-sql EF 查询以匹配特定的 JSON 结构
【发布时间】:2016-10-06 15:19:28
【问题描述】:

我的 JSON 具有以下结构:

[

  {

    "ID": 1,

    "Label": "Reg Scheme",

    "Colours": [

      {

        "ID": 1,

        "Value": "0x3333cc",

        "Result": 1,

        "Label": null

      },

      {

        "ID": 2,

        "Value": "0x666699",

        "Result": 2,

        "Label": null

      },

      {

        "ID": 3,

        "Value": "0x009966",

        "Result": 3,

        "Label": null

      }

    ]

  },

  {

    "ID": 2,

    "Label": "Spesh Scheme",

    "Colours": [

      {

        "ID": 11,

        "Value": "0x59699c",

        "Result": 1,

        "Label": null

      },

      {

        "ID": 12,

        "Value": "0x0070ff",

        "Result": 2,

        "Label": null

      },

      {

        "ID": 13,

        "Value": "0x90865e",

        "Result": 3,

        "Label": null

      }

    ]

  },

我有一个实体数据集,我已经加入了所有相关信息,并试图通过单个 linq-to-sql EF 查询生成具有该结构的 JSON,以返回给 webapi 方法。

到目前为止我的查询是:

return
    DbContext.Schemes
            .Join(
                DbContext.SchemeColours,
                s => s.SchemeID,
                sc => sc.SchemeID,
                (s, sc) => new
                    {
                        s.SchemeID,
                        s.Label,
                        sc.Colour,
                        sc.Result,
                        sc.ColourID
                    })
            .Select(a =>
                    new Overlay.ReportColourScheme
                        {
                            ID = a.SchemeID,
                            Label = a.Label,
                            Colours = new List<Overlay.ReportColour>
                                {
                                    new Overlay.ReportColour
                                        {
                                            ID = a.ColourID,
                                            Value = a.Colour,
                                            Result = a.Result
                                        }
                                }
                        })
            .ToArray();

几乎有但不完全:

[

  {

    "ID": 1,

    "Label": "Regular Scheme",

    "Colours": [

      {

        "ID": 1,

        "Value": "0x3333cc",

        "Result": 1,

        "Label": null

      }

    ]

  },

  {

    "ID": 1,

    "Label": "Regular Scheme",

    "Colours": [

      {

        "ID": 2,

        "Value": "0x666699",

        "Result": 2,

        "Label": null

      }

    ]

  },

  {

    "ID": 1,

    "Label": "Regular Scheme",

    "Colours": [

      {

        "ID": 3,

        "Value": "0x009966",

        "Result": 3,

        "Label": null

      }

    ]

  },

  {

    "ID": 2,

    "Label": "Protanopia adjusted Scheme",

    "Colours": [

      {

        "ID": 11,

        "Value": "0x59699c",

        "Result": 1,

        "Label": null

      }

    ]

  },

  {

    "ID": 2,

    "Label": "Protanopia adjusted Scheme",

    "Colours": [

      {

        "ID": 12,

        "Value": "0x0070ff",

        "Result": 2,

        "Label": null

      }

    ]

  },

  {

    "ID": 2,

    "Label": "Protanopia adjusted Scheme",

    "Colours": [

      {

        "ID": 13,

        "Value": "0x90865e",

        "Result": 3,

        "Label": null

      }

    ]

  },

当然,它会为每个 resultID 创建一个新列表。顶级 ID 是一个 SchemeID-我正在寻找的逻辑是这样的:“获取具有特定 schemeID 的前 3 个结果,将它们添加到颜色列表中,然后转到下一个 schemeID”

我相信这会产生与我开始发帖时使用的相同的 JSON。

任何帮助都将不胜感激,谢谢。

【问题讨论】:

  • 第一次加入后是否尝试按 SchemeID 分组?这应该会产生你想要的结果。

标签: c# asp.net json entity-framework linq


【解决方案1】:

试试下面的代码:

return
    DbContext.Schemes
            .Join(
                DbContext.SchemeColours,
                s => s.SchemeID,
                sc => sc.SchemeID,
                (s, sc) => new
                    {
                        s.SchemeID,
                        s.Label,
                        sc.Colour,
                        sc.Result,
                        sc.ColourID
                    })
            // After joining you group by SchemeID, in this way you have 
            // for each SchemeID the group of related items
            .GroupBy(a => a.SchemeID)
            // You then create your result, starting from the main object
            .Select(g =>
                    new Overlay.ReportColourScheme
                        {
                            ID = g.Key,
                            // I suppose you have at least a child for each SchemeID, 
                            // otherwise you can check if the list is empty
                            Label = g.FirstOrDefault().Label,
                            // For each group you create a list of child object
                            Colours = g.Select(v => new Overlay.ReportColour
                                        {
                                            ID = v.ColourID,
                                            Value = v.Colour,
                                            Result = v.Result
                                        }).ToList()
                        })
            .ToArray();

【讨论】:

  • 你可能都是正确的,但是标记的答案在 EF 中更简洁
  • @notsoobvious 没问题兄弟 :)
【解决方案2】:

主要问题是您使用的是Join,而实际上您需要Group Join

return DbContext.Schemes
    .GroupJoin(DbContext.SchemeColours,
        s => s.SchemeID,
        sc => sc.SchemeID,
        (s, colours) => new Overlay.ReportColourScheme
        {
            ID = s.SchemeID,
            Label = s.Label,
            Colours = colours
                .Select(sc => new Overlay.ReportColour
                {
                    ID = sc.ColourID,
                    Value = sc.Colour,
                    Result = sc.Result,
                })
                .ToList()
        })
    .ToArray();

但由于您使用的是实体框架,如果您定义(如果您还没有)并使用 导航属性,会更好、更轻松:

class Scheme
{
    // ...
    public ICollection<SchemeColour> Colours { get; set; }
}

然后简单

return DbContext.Schemes
    .Select(s => new Overlay.ReportColourScheme
    {
        ID = s.SchemeID,
        Label = s.Label,
        Colours = s.Colours
            .Select(sc => new Overlay.ReportColour
            {
                ID = sc.ColourID,
                Value = sc.Colour,
                Result = sc.Result,
            })
           .ToList()
    })
    .ToArray();

【讨论】:

    猜你喜欢
    • 2017-03-10
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多