在Linq查询中设置变量

时间:2017-09-07 21:58:09

标签: c# linq

我正在对查询应用过滤器,我正在尝试在其中一个过滤器中设置变量值。我尝试了各种在线示例,但每种都以不同的方式失败。

问:如何在下面的示例中设置MeterObjectState变量?

我试过了:

  • 使用LET
  • 使用SELECT( x=> { x.MeterObjectState = dataitems.Workflow; return x; })

......和其他人。

数据传输对象示例:
这是属性的部分列表:

public class DeviceDataItem
{
    public int DeviceId { get; set; }

    public string DeviceName { get; set; }

    public int? MeterId { get; set; }

    public string MeterName { get; set; }

    public Workflow MeterObjectState { get; set; } //<-- I am trying to set this

    // Other properties omitted ...
}

METER WORKFLOW FILTER:
我想做dataitems.Workflow = statefulDevice.Workflow

之类的事情
public IQueryable<DeviceDataItem> MeterWorkflowFilter(IQueryable<DeviceDataItem> query)
{
    Type context = typeof(Meter);

    var deviceState = (from objectState in UnitOfWork.ObjectState
                       join workflow in UnitOfWork.Workflow 
                       on objectState.WorkflowId equals workflow.Id
                       where objectState.ContextFullName == context.FullName
                       group objectState by objectState.ContextId into grp
                       select grp.OrderByDescending(desc => desc.CreateDate)
                       .FirstOrDefault());

    // NOTE: Here is where I have access to "statefulDevice.Workflow"
    // and want to do something like "dataitems.Workflow = statefulDevice.Workflow"
    var filteredQuery = (from dataitems in query //<-- QUERY
                         join statefulDevice in deviceState 
                         on dataitems.MeterId equals statefulDevice.ContextId 
                         into statefulDeviceLEFTJOIN
                         from statefulDevice in statefulDeviceLEFTJOIN.DefaultIfEmpty()
                         select dataitems.Workflow = statefulDevice.Workflow);

    return filteredQuery;
}

原始查询过滤器:
您不应该需要这个来回答这个问题......但是人们经常会要求更多细节

public IQueryable<DeviceDataItem> Query()
{
    var query = from device in UnitOfWork.Device
                join rtuDevice in UnitOfWork.RTUDevice on device.Id equals rtuDevice.DeviceId into rtuDeviceLEFTJOIN
                    from rtuDevice in rtuDeviceLEFTJOIN.DefaultIfEmpty()
                join commTech in UnitOfWork.User on rtuDevice.CommunicationTechnicianId equals commTech.Id into commTechLEFTJOIN
                    from commTech in commTechLEFTJOIN.DefaultIfEmpty()
                join measureTech in UnitOfWork.User on rtuDevice.MeasurementTechnicianId equals measureTech.Id into measureTechLEFTJOIN
                    from measureTech in measureTechLEFTJOIN.DefaultIfEmpty()
                join meter in UnitOfWork.Meter on device.Id equals meter.DeviceId into meterLEFTJOIN
                    from meter in meterLEFTJOIN.DefaultIfEmpty()
                join meterType in UnitOfWork.MeterType on meter.MeterTypeId equals meterType.Id into meterTypeLEFTJOIN
                    from meterType in meterTypeLEFTJOIN.DefaultIfEmpty()
                join company in UnitOfWork.Company on meter.CompanyId equals company.Id into companyLEFTJOIN
                    from company in companyLEFTJOIN.DefaultIfEmpty()
                join meterPosition in UnitOfWork.EFMMeterPosition on meter.EFMMeterPositionId equals meterPosition.Id into meterPositionLEFTJOIN
                    from meterPosition in meterPositionLEFTJOIN.DefaultIfEmpty()
                join runStatus in UnitOfWork.RunStatus on meter.RunStatusId equals runStatus.Id into runStatusLEFTJOIN
                    from runStatus in runStatusLEFTJOIN.DefaultIfEmpty()
                join pipeline in UnitOfWork.Pipeline on meter.PipelineId equals pipeline.Id into pipelineLEFTJOIN
                    from pipeline in pipelineLEFTJOIN.DefaultIfEmpty()
                select new DeviceDataItem()
                {
                    DeviceId = device.Id,
                    DeviceName = device.DeviceName,
                    MeterPositionId = meterPosition.Id,
                    MeterPositionCategory = meterPosition.EFMMeterPositionCategory,
                    MeterId = meter.Id,
                    MeterName = meter.MeterName,
                    MeterNumber = meter.MeterNumber,
                    MeterTypeId = meterType.Id,
                    MeterTypeName = meterType.MeterTypeName,
                    CompanyId = company.Id,
                    CompanyName = company.CompanyName,
                    PipelineId = pipeline.Id,
                    PipelineName = pipeline.PipelineName,
                    CommunicationTechnicianId = commTech.Id,
                    CommunicationTechnicianFirstName = commTech.FirstName,
                    CommunicationTechnicianLastName = commTech.LastName,
                    MeasurementTechnicianId = measureTech.Id,
                    MeasurementTechnicianFirstName = measureTech.FirstName,
                    MeasurementTechnicianLastName = measureTech.LastName,
                    RunStatusId = runStatus.Id,
                    RunStatusCategory = runStatus.RunStatusCategory,
                };

    return query;
}

用法:
您不应该需要这个来回答这个问题......但是人们经常会要求更多细节

var application = (MeasurementContractsApplication)MeasurementContracts;
var provider = (DeviceDataItemProvider)application.DeviceDataItemProvider;

var query = provider.Query();
var publishedDevices = provider.PublishedDevicesFilter(query);
var meterByWorkflow = provider.MeterWorkflowFilter(query);

var collection = meterByWorkflow.ToDataSourceResult(request).ToList();

2 个答案:

答案 0 :(得分:0)

我讨厌发布自己的答案。如果有人提出更有说服力的解决方案,我很乐意将其标记为正确。

<强>步骤进行:

  1. 将“MeterObjectState”添加到原始查询SELECT CLAUSE
  2. 设置新属性时,请确保为每个“过滤器”
  3. 返回相同的SELECT CLAUSE

    <强>说明
    事实证明,您可以在Linq查询链中多次“重置一个select子句”。但是,“数据传输对象”的组合在所有查询中必须完全相同。因此,当您使用所述“过滤器”构建原始查询时,只需“重新创建”新的返回集。

    为什么不首先实现这一目标?:
    如果我实现它,那么我在操作内存中的对象。这样,我可以让实体框架首先通过实现计划优化查询。

    ...耶!

    为什么我喜欢这个?:
    原始查询无需担心原始查询中任何实体的“工作流或对象状态”。但是,其他情况要求我关心各种实体的当前“状态”。现在,我可以随时将过滤器应用于原始查询...而无需重写原始查询的变体。另外,请注意我不需要实现查询来实现此目的。

    因此...

    • 一个查询
    • 多个过滤器
    • 过滤器可以优化记录或附加到其中

    ......我喜欢那样。

    最终查询:
    在这里,我只是将“MeterObjectState”添加到属性的DeciveDataItem列表中。记住,您可以“重新投射”查询MULTIPLE TIMES ...但仅当SELECT CLAUSE在查询的整个生命周期内保持不变时。

    public IQueryable<DeviceDataItem> Query()
    {
        var query = from device in UnitOfWork.Device
                    join rtuDevice in UnitOfWork.RTUDevice on device.Id equals rtuDevice.DeviceId into rtuDeviceLEFTJOIN
                    from rtuDevice in rtuDeviceLEFTJOIN.DefaultIfEmpty()
                    join commTech in UnitOfWork.User on rtuDevice.CommunicationTechnicianId equals commTech.Id into commTechLEFTJOIN
                    from commTech in commTechLEFTJOIN.DefaultIfEmpty()
                    join measureTech in UnitOfWork.User on rtuDevice.MeasurementTechnicianId equals measureTech.Id into measureTechLEFTJOIN
                    from measureTech in measureTechLEFTJOIN.DefaultIfEmpty()
                    join meter in UnitOfWork.Meter on device.Id equals meter.DeviceId into meterLEFTJOIN
                    from meter in meterLEFTJOIN.DefaultIfEmpty()
                    join meterType in UnitOfWork.MeterType on meter.MeterTypeId equals meterType.Id into meterTypeLEFTJOIN
                    from meterType in meterTypeLEFTJOIN.DefaultIfEmpty()
                    join company in UnitOfWork.Company on meter.CompanyId equals company.Id into companyLEFTJOIN
                    from company in companyLEFTJOIN.DefaultIfEmpty()
                    join meterPosition in UnitOfWork.EFMMeterPosition on meter.EFMMeterPositionId equals meterPosition.Id into meterPositionLEFTJOIN
                    from meterPosition in meterPositionLEFTJOIN.DefaultIfEmpty()
                    join runStatus in UnitOfWork.RunStatus on meter.RunStatusId equals runStatus.Id into runStatusLEFTJOIN
                    from runStatus in runStatusLEFTJOIN.DefaultIfEmpty()
                    join pipeline in UnitOfWork.Pipeline on meter.PipelineId equals pipeline.Id into pipelineLEFTJOIN
                    from pipeline in pipelineLEFTJOIN.DefaultIfEmpty()
                    select new DeviceDataItem()
                    {
                        DeviceId = device.Id,
                        DeviceName = device.DeviceName,
                        MeterPositionId = meterPosition.Id,
                        MeterPositionCategory = meterPosition.EFMMeterPositionCategory,
                        MeterId = meter.Id,
                        MeterName = meter.MeterName,
                        MeterNumber = meter.MeterNumber,
                        MeterTypeId = meterType.Id,
                        MeterTypeName = meterType.MeterTypeName,
                        CompanyId = company.Id,
                        CompanyName = company.CompanyName,
                        PipelineId = pipeline.Id,
                        PipelineName = pipeline.PipelineName,
                        CommunicationTechnicianId = commTech.Id,
                        CommunicationTechnicianFirstName = commTech.FirstName,
                        CommunicationTechnicianLastName = commTech.LastName,
                        MeasurementTechnicianId = measureTech.Id,
                        MeasurementTechnicianFirstName = measureTech.FirstName,
                        MeasurementTechnicianLastName = measureTech.LastName,
                        RunStatusId = runStatus.Id,
                        RunStatusCategory = runStatus.RunStatusCategory,
                        MeterObjectState = null
                    };
    
        return query;
    }
    

    最终过滤器:
    在这里,我正在填写一个理想的财产&amp;回归“新鲜”......

    public IQueryable<DeviceDataItem> MeterWorkflowFilter(IQueryable<DeviceDataItem> query)
    {
        Type context = typeof(Meter);
    
        var deviceState = (from objectState in UnitOfWork.ObjectState
                           join workflow in UnitOfWork.Workflow on objectState.WorkflowId equals workflow.Id
                           where
                                objectState.ContextFullName == context.FullName
                           group objectState by objectState.ContextId into grp
                           select grp.OrderByDescending(desc => desc.CreateDate).FirstOrDefault());
    
        // NOTE: Not all Devices will immediately have a Meter
        var filteredQuery = (from dataitems in query //<-- QUERY
                             join statefulDevice in deviceState on dataitems.MeterId equals statefulDevice.ContextId into statefulDeviceLEFTJOIN
                             from statefulDevice in statefulDeviceLEFTJOIN.DefaultIfEmpty()
                             select new DeviceDataItem()
                             {
                                 DeviceId = dataitems.DeviceId,
                                 DeviceName = dataitems.DeviceName,
                                 MeterPositionId = dataitems.MeterPositionId,
                                 MeterPositionCategory = dataitems.MeterPositionCategory,
                                 MeterId = dataitems.MeterId,
                                 MeterName = dataitems.MeterName,
                                 MeterNumber = dataitems.MeterNumber,
                                 MeterTypeId = dataitems.MeterTypeId,
                                 MeterTypeName = dataitems.MeterTypeName,
                                 CompanyId = dataitems.CompanyId,
                                 CompanyName = dataitems.CompanyName,
                                 PipelineId = dataitems.PipelineId,
                                 PipelineName = dataitems.PipelineName,
                                 CommunicationTechnicianId = dataitems.CommunicationTechnicianId,
                                 CommunicationTechnicianFirstName = dataitems.CommunicationTechnicianFirstName,
                                 CommunicationTechnicianLastName = dataitems.CommunicationTechnicianLastName,
                                 MeasurementTechnicianId = dataitems.MeasurementTechnicianId,
                                 MeasurementTechnicianFirstName = dataitems.MeasurementTechnicianFirstName,
                                 MeasurementTechnicianLastName = dataitems.MeasurementTechnicianLastName,
                                 RunStatusId = dataitems.RunStatusId,
                                 RunStatusCategory = dataitems.RunStatusCategory,
                                 MeterObjectState = statefulDevice.Workflow
                             });
    
        return filteredQuery;
    }
    

答案 1 :(得分:0)

如果您获得Microsoft的Interactive Extensions(Ix) - 只需NuGet&#34; System.Interactive&#34; - 那么你可以这样做:

void Main()
{
    var foos = new List<Foo>()
    {
        new Foo() { Bar = 1 }
    };

    foreach (var f in foos.Do(f => f.Bar = 42))
    {
        Console.WriteLine(f.Bar);
    }
}

public class Foo
{
    public int Bar;
}

这会输出42