如何使用可枚举类型从Linq创建结果集?

时间:2016-10-10 14:01:17

标签: c# linq

结果集如下:

ServiceName                                     Ping                                                         Desc                       LogName                                         BaseUrl                          EnvName         
IntegrationServices.BillingInstructionsService /IntegrationServices/BillingInstructionsService.svc/Rest/Ping BillingInstructionsService IntegrationServices.BillingInstructionsServices https://icrDev.xxx.com   Dev 
IntegrationServices.BillingInstructionsService /IntegrationServices/BillingInstructionsService.svc/Rest/Ping BillingInstructionsService IntegrationServices.BillingInstructionsServices https://IUTD01.xxx.com   DevUnitTest 
IntegrationServices.BillingInstructionsService /IntegrationServices/BillingInstructionsService.svc/Rest/Ping BillingInstructionsService IntegrationServices.BillingInstructionsServices https://ickd01.xxx.com    DevClock 
IntegrationServices.BillingInstructionsService /IntegrationServices/BillingInstructionsService.svc/Rest/Ping BillingInstructionsService IntegrationServices.BillingInstructionsServices https://icd01.xxx.com     DevConv 

从linq查询返回,我的需求可以过滤(ServiceId)或未过滤......:

var data = contextObj.ServiceMonitorMappings
            .Where(r => r.ServiceId == 33)
            .Select(x => new
            {
                ServiceName = x.Service.Name,
                Ping = x.Service.PingUrl,
                Desc = x.Service.Description,
                LogName = x.ServiceLoggingName.LoggingName,
                BaseUrl = x.ServiceBaseUrl.ServiceBaseUrl1,
                EnvName = x.ServiceEnvironment.Name
            });

ServiceMonitorMapping看起来像这样:

public partial class ServiceMonitorMapping
{
public int Id { get; set; }
public int ServiceEnvironmentId { get; set; }
public int ServiceId { get; set; }
public int ServiceLoggingNameId { get; set; }
public int ServiceBaseUrlId { get; set; }

public virtual Service Service { get; set; }
public virtual ServiceLoggingName ServiceLoggingName { get; set; }
public virtual ServiceBaseUrl ServiceBaseUrl { get; set; }
public virtual ServiceEnvironment ServiceEnvironment { get; set; }
}

我试图让BaseUrl和EnvName作为一个可枚举的集合返回,这样我就不会有4条记录而是1条,其中最后2列包含BaseUrl和EnvName的列表,但我找不到办法做到这一点。所以我坚持4条记录而不是1条。对我来说似乎并不理想。

所以我的问题是这样,是否可以返回1行,最后2列是一个集合,这样我就有“项目项目项目列表<>列表<>”?

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

var data = contextObj.ServiceMonitorMappings
            .Where(r => r.ServiceId == 33)
            .Select(x => new
            {
                Key = new {ServiceName = x.Service.Name,
                           Ping = x.Service.PingUrl,
                           Desc = x.Service.Description,
                           LogName = x.ServiceLoggingName.LoggingName};
                BaseUrl = x.ServiceBaseUrl.ServiceBaseUrl1,
                EnvName = x.ServiceEnvironment.Name
            })
            .GroupBy(x => x.Key)
            .Select(g => new
            {
              ServiceName = g.Key.ServiceName,
              Ping = g.Key.Ping,
              Desc = g.Key.Desc,
              LogName = g.Key.LogName,
              BaseUrls = g.Select(x => x.BaseUrl).ToList(),
              EnvNames = g.Select(x => x.EnvName ).ToList();
            })

答案 1 :(得分:1)

虽然tolanj的答案相当不错,但我相信这不是最简单的方法。您可以在分组后使用Select来简化查询:

var data = contextObj.ServiceMonitorMappings
            .GroupBy(r => r.ServiceId)
            .Where(r => r.Key == 33)
            .Select(x => new
            {
                ServiceName = x.First().Service.Name,
                Ping = x.First().Service.PingUrl,
                Desc = x.First().Service.Description,
                LogName = x.First().ServiceLoggingName.LoggingName,
                BaseUrl = x.Select(y => y.ServiceBaseUrl.ServiceBaseUrl1).ToList(), //ToList is optional
                EnvName = x.Select(y => y.ServiceEnvironment.Name).ToList() //ToList is optional
            });

起初,我没有注意到这是通过LINQ to SQL进行的数据库查询。为了使用这种方法并且由于下载整个表而没有失去性能,你可以这样尝试:

var data = contextObj.ServiceMonitorMappings
            .Where(r => r.ServiceId == 33)
            .AsEnumerable()  //AsEnumerable after Where to apply filter on the DB query
            .GroupBy(x => 1) //data already filtered, only one group as a result
            .Select(x => new
            {
                ServiceName = x.First().Service.Name,
                Ping = x.First().Service.PingUrl,
                Desc = x.First().Service.Description,
                LogName = x.First().ServiceLoggingName.LoggingName,
                BaseUrl = x.Select(y => y.ServiceBaseUrl.ServiceBaseUrl1).ToList(), //ToList is optional
                EnvName = x.Select(y => y.ServiceEnvironment.Name).ToList() //ToList is optional
            });

答案 2 :(得分:0)

我希望你了解你的需求;我用这种方式解决了:

var query = contextObj.ServiceMonitorMappings
    .Where(r => r.ServiceId == 33)
    .Select(d => new { 
                 BaseUrl = d.ServiceBaseUrl.ServiceBaseUrl1, 
                 EnvName = d.ServiceEnvironment.Name})
    .Aggregate((d1, d2) =>
    new {
        BaseUrl = d1.BaseUrl + ", " + d2.BaseUrl,
        EnvName = d1.EnvName + ", " + d2.EnvName
    });

结果如下:

BaseUrl
https://icrDev.xxx.com, https://IUTD01.xxx.com, https://ickd01.xxx.co, https://icd01.xxx.com 
EnvName 
Dev, DevUnitTest, DevClock, DevConv

修改

我已更改查询以返回您需要的结果:

var query = contextObj.ServiceMonitorMappings
    .Where(r => r.ServiceId == 33)
    .Select(d => new { 
                 BaseUrl = d.ServiceBaseUrl.ServiceBaseUrl1, 
                 EnvName = d.ServiceEnvironment.Name})
        .Aggregate(
            //initialize the accumulator
            new { BaseUrl = new List<string>(), EnvName = new List<string>() }, 
            (acc, next) => //accumulator and nextItem
            {
                acc.BaseUrl.Add(next.BaseUrl);
                acc.EnvName.Add(next.EnvName);
                return acc;
            });