开发者

LINQ, select with only the first element of child item

开发者 https://www.devze.com 2023-03-25 07:30 出处:网络
With LINQ, how to do a select and only return the first associated child item? I have: [table: Report] GeneratedDate

With LINQ, how to do a select and only return the first associated child item?

I have:

[table: Report]
    GeneratedDate
    PerformanceMetric  1 -----> N [table PerformanceMetric]
    Bios                              Timestamp
    ...                               X
                                      Y 
                                      ..... (there is a good dozen other fields)

Currently, I do:

 Report = _ctx.Reports.SingleorDefault(rpt => rpt.bios == mySerial);

This returns t开发者_如何学JAVAhe report with all the PerformanceMetric associated. I would like to only have the first occurrence of PerformanceMetric returned.

Does LINQ provide a built-in way of doing so?

EDIT: In fact, I am looking for the Report, but the PerformanceMetric should only contain the first element. (Report.PerformanceMetrics.Count <= 1 ) sry for not being clear..


Hard to tell exactly the full structure based on your XML, but something like:

var firstMetric = _ctx.Reports
    .Where(rpt => rpt.bios == mySerial)
    .Select(rpt => rpt.PerformanceMetrics) // assuming name here...
    .FirstOrDefault();

This returns the first performance metric of the report matching mySerial, or default (null for classes) if the where clause didn't find any reports or no performance metrics existed.

Update: based on the update in the question, you want something different. You want the report, but with only 1 of the performance metrics. This involves mutating the original report (not sure of all the members), which can be kinda hairy because you don't want to manipulate your original data in LINQ.

So you have two options:

  1. You can create a new instance of Report and copy all the properties and just one metric.
  2. You can create an anonymous type with the report and the property together.

I'd probably prefer #2 since returning a modified Report might be confusing. So you could do:

var firstMetric = _ctx.Reports
    .Where(rpt => rpt.bios == mySerial)
    .Select(new { Report = rpt, Metric = rpt.PerformanceMetrics.FirstOrDefault() })
    .FirstOrDefault();

This will scan the Reports for the one where bios == mySerial, create a new anonymous type with a Report member == to the original report, and a Metric member == the first metric in the Report list.

If no metrics exist but report exists, you'll get an anonymous type with Report = your report and Metric = null. If no report exists matching condition, returns null.

If you do really want #1, you could do this:

var firstMetric = _ctx.Reports
    .Where(rpt => rpt.bios == mySerial)
    .Select(new Report 
        { 
            PerformanceMetrics = rpt.PerformanceMetrics.Take(1),
            // copy all other Report fields here...
        })
    .FirstOrDefault();


Are you looking for something like this?

var reportMetric = (from r in _ctx.Reports select r.PerformanceMetric where r.Bios == mySerial).FirstOrDefault();
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号