public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { EventKey eventKey = CreateEventKey(meterDataSet.FileGroup, cycleDataResource.DataGroups[i]); VICycleDataGroup viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; int samplesPerCycle = (int)Math.Round(cycleDataResource.DataGroups[i].SamplesPerSecond / m_systemFrequency); Process(eventKey, viCycleDataGroup, samplesPerCycle); } m_meterDataSet = meterDataSet; using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { // Query database for events and store them in a lookup table by event key TableOperations <Event> eventAdapter = new TableOperations <Event>(connection); TableOperations <CycleData> cycleDataAdapter = new TableOperations <CycleData>(connection); IEnumerable <Event> eventTable = eventAdapter.QueryRecordsWhere("FileGroupID = {0}", m_meterDataSet.FileGroup.ID); Dictionary <EventKey, Event> eventLookup = eventTable.ToDictionary(CreateEventKey); foreach (Tuple <EventKey, CycleData> tuple in m_cycleDataList) { Event eventRow; if (eventLookup.TryGetValue(tuple.Item1, out eventRow)) { tuple.Item2.EventID = eventRow.ID; cycleDataAdapter.AddNewRecord(tuple.Item2); } } } }
public override void Execute(MeterDataSet meterDataSet) { m_incidents = new List <Incident>(); CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); if (!cycleDataResource.DataGroups.Any()) { return; } DateTime startTime = cycleDataResource.DataGroups.Min(dataGroup => dataGroup.StartTime); DateTime endTime = cycleDataResource.DataGroups.Max(dataGroup => dataGroup.EndTime); using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { DataTable incidentTable = connection.RetrieveData("SELECT * FROM GetNearbyIncidents({0},{1},{2},{3})", meterDataSet.Meter.ID, startTime, endTime, m_timeTolerance); IEnumerable <Range <DateTime> > ranges = incidentTable.Select().Select(incident => ToRange(DateTime.Parse(incident["StartTime"].ToString()), DateTime.Parse(incident["EndTime"].ToString()))) .Concat(cycleDataResource.DataGroups.Select(dataGroup => ToRange(dataGroup.StartTime, dataGroup.EndTime))); m_incidents = Range <DateTime> .MergeAllOverlapping(ranges) .Select(ToIncident) .ToList(); foreach (Incident incident in m_incidents) { incident.ExistingIncidents = incidentTable.Select().Where(row => Overlaps(incident, row)).ToList(); } m_meterID = meterDataSet.Meter.ID; Load(connection); } }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource; DataGroup dataGroup; VIDataGroup viDataGroup; VICycleDataGroup viCycleDataGroup; cycleDataResource = CycleDataResource.GetResource(meterDataSet, m_dbAdapterContainer); m_breakerCurrents = new HashSet <string>(cycleDataResource.DataGroups .Where(dg => dg.Line.AssetKey.StartsWith("BR")) .SelectMany(dg => dg.DataSeries) .SelectMany(ds => ds.SeriesInfo.Channel.BreakerChannels) .Select(ch => ch.BreakerNumber)); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { dataGroup = cycleDataResource.DataGroups[i]; viDataGroup = cycleDataResource.VIDataGroups[i]; viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; IdentifyBreakerOperations(dataGroup, viDataGroup, viCycleDataGroup); } m_meterDataSet = meterDataSet; }
public void WriteResults(DbAdapterContainer dbAdapterContainer, MeterDataSet meterDataSet) { CycleDataResource cycleDataResource; FaultDataResource faultDataResource; DataGroup dataGroup; VICycleDataGroup viCycleDataGroup; FaultGroup faultGroup; string rootFileName; string fileName; cycleDataResource = meterDataSet.GetResource(() => CycleDataResource.GetResource(meterDataSet, dbAdapterContainer)); faultDataResource = meterDataSet.GetResource(() => new FaultDataResource(dbAdapterContainer)); if (!Directory.Exists(m_resultsPath)) { Directory.CreateDirectory(m_resultsPath); } for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { dataGroup = cycleDataResource.DataGroups[i]; if (faultDataResource.FaultLookup.TryGetValue(dataGroup, out faultGroup)) { rootFileName = FilePath.GetFileNameWithoutExtension(meterDataSet.FilePath); fileName = string.Format("{0},{1:000},Line{2}.xml", rootFileName, i, dataGroup.Line.AssetKey); viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; WriteResults(meterDataSet, dataGroup, viCycleDataGroup, faultGroup.Faults, Path.Combine(m_resultsPath, fileName)); } } }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); SagDataResource sagDataResource = meterDataSet.GetResource <SagDataResource>(); SwellDataResource swellDataResource = meterDataSet.GetResource <SwellDataResource>(); InterruptionDataResource interruptionDataResource = meterDataSet.GetResource <InterruptionDataResource>(); using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { TableOperations <Disturbance> disturbanceTable = new TableOperations <Disturbance>(connection); TableOperations <DisturbanceSeverity> disturbanceSeverityTable = new TableOperations <DisturbanceSeverity>(connection); TableOperations <VoltageEnvelope> voltageEnvelopeTable = new TableOperations <VoltageEnvelope>(connection); TableOperations <VoltageCurve> voltageCurveTable = new TableOperations <VoltageCurve>(connection); TableOperations <VoltageCurvePoint> voltageCurvePointTable = new TableOperations <VoltageCurvePoint>(connection); List <Disturbance> disturbances = disturbanceTable .QueryRecordsWhere("EventID IN (SELECT ID FROM Event WHERE FileGroupID = {0})", meterDataSet.FileGroup.ID) .ToList(); foreach (VoltageEnvelope voltageEnvelope in voltageEnvelopeTable.QueryRecords().ToList()) { List <VoltageCurve> voltageCurves = voltageCurveTable .QueryRecordsWhere("ID IN (SELECT VoltageCurveID FROM VoltageEnvelopeCurve WHERE VoltageEnvelopeID = {0})", voltageEnvelope.ID) .ToList(); foreach (VoltageCurve voltageCurve in voltageCurves) { voltageCurve.VoltageCurvePoints = voltageCurvePointTable .QueryRecordsWhere("VoltageCurveID = {0}", voltageCurve.ID) .ToList(); } foreach (Disturbance disturbance in disturbances) { int maxSeverityCode = voltageCurves .Select(voltageCurve => voltageCurve.GetMagnitude(disturbance.DurationSeconds)) .Select(curveMagnitude => (int)((1.0D - disturbance.PerUnitMagnitude) / (1.0D - curveMagnitude))) .DefaultIfEmpty(0) .Max(); if (maxSeverityCode < 0) { maxSeverityCode = 0; } else if (maxSeverityCode > 5) { maxSeverityCode = 5; } disturbanceSeverityTable.AddNewRecord(new DisturbanceSeverity() { VoltageEnvelopeID = voltageEnvelope.ID, DisturbanceID = disturbance.ID, SeverityCode = maxSeverityCode }); } } } }
public override void Execute(MeterDataSet meterDataSet) { // The following logic should only apply to NEXUS meters, not DFRs if (!meterDataSet.Meter.Model.StartsWith("NEXUS")) { return; } CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); EventClassificationResource eventClassificationResource = meterDataSet.GetResource <EventClassificationResource>(); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { DataGroup dataGroup = cycleDataResource.DataGroups[i]; VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i]; double llPeakNominalVoltage = dataGroup.Asset.VoltageKV * 1000.0D * Math.Sqrt(2.0D); double lnPeakNominalVoltage = llPeakNominalVoltage / Math.Sqrt(3.0D); // Nominal multipliers used for first derivative, based on: // d/dt(A*sin(w*t)) = A*w*cos(w*t) double omega = 2.0D * Math.PI * SystemFrequency; double llFactor = 1.0D / (llPeakNominalVoltage * omega); double lnFactor = 1.0D / (lnPeakNominalVoltage * omega); DataSeries[] puVoltages = { viDataGroup.VA?.Multiply(lnFactor), viDataGroup.VB?.Multiply(lnFactor), viDataGroup.VC?.Multiply(lnFactor), viDataGroup.VAB?.Multiply(llFactor), viDataGroup.VBC?.Multiply(llFactor), viDataGroup.VCA?.Multiply(llFactor) }; bool invalidVoltage = false; foreach (DataSeries voltage in puVoltages) { if (voltage == null) { continue; } List <DataPoint> dataPoints = voltage.DataPoints; invalidVoltage |= dataPoints .Zip(dataPoints.Skip(1), (p1, p2) => (p2.Value - p1.Value) / (p2.Time - p1.Time).TotalSeconds) .Any(slope => Math.Abs(slope) > Settings.MaxVoltageSlope); } if (invalidVoltage) { eventClassificationResource.Classifications[dataGroup] = EventClassification.MeterDataQuality; } } }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource; EventClassificationResource eventClassificationResource; Log.Info("Executing operation to load event data into the database..."); cycleDataResource = CycleDataResource.GetResource(meterDataSet, m_dbAdapterContainer); eventClassificationResource = meterDataSet.GetResource(() => new EventClassificationResource(m_dbAdapterContainer)); LoadEvents(meterDataSet, cycleDataResource.DataGroups, cycleDataResource.VICycleDataGroups, eventClassificationResource.Classifications); LoadDisturbances(meterDataSet, cycleDataResource.DataGroups); m_meterDataSet = meterDataSet; }
public void WriteResults(DbAdapterContainer dbAdapterContainer, MeterDataSet meterDataSet) { CycleDataResource cycleDataResource; FaultDataResource faultDataResource; DataGroup dataGroup; FaultGroup faultGroup; List <int> seriesIDs; EventDataSet eventDataSet; string rootFileName; string fileName; cycleDataResource = meterDataSet.GetResource(() => CycleDataResource.GetResource(meterDataSet, dbAdapterContainer)); faultDataResource = meterDataSet.GetResource(() => new FaultDataResource(dbAdapterContainer)); if (!Directory.Exists(m_resultsPath)) { Directory.CreateDirectory(m_resultsPath); } for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { dataGroup = cycleDataResource.DataGroups[i]; if (faultDataResource.FaultLookup.TryGetValue(dataGroup, out faultGroup)) { rootFileName = FilePath.GetFileNameWithoutExtension(meterDataSet.FilePath); fileName = string.Format("{0},{1:000},Line{2}.dat", rootFileName, i, dataGroup.Line.AssetKey); seriesIDs = dataGroup.DataSeries .Select(series => series.SeriesInfo.ID) .ToList(); eventDataSet = new EventDataSet() { ResultsPath = Path.Combine(m_resultsPath, fileName), MeterDataSet = meterDataSet, TimeZoneOffset = GetTimeZoneOffset(meterDataSet.Meter.TimeZone, dataGroup.StartTime), DataGroup = dataGroup, VICycleDataGroup = cycleDataResource.VICycleDataGroups[i], Faults = faultGroup.Faults, OutputChannels = dbAdapterContainer.GetAdapter <FaultLocationInfoDataContext>().OutputChannels.Where(channel => seriesIDs.Contains(channel.SeriesID)).ToList() }; WriteResults(eventDataSet); } } }
public override void Execute(MeterDataSet meterDataSet) { DataGroupsResource dataGroupsResource = meterDataSet.GetResource <DataGroupsResource>(); CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); EventClassificationResource eventClassificationResource = meterDataSet.GetResource <EventClassificationResource>(); using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { List <DataGroup> dataGroups = new List <DataGroup>(cycleDataResource.DataGroups); dataGroups.AddRange(dataGroupsResource.DataGroups.Where(dataGroup => dataGroup.DataSeries.Count == 0)); List <Event> events = GetEvents(connection, meterDataSet, dataGroups, cycleDataResource.VICycleDataGroups, eventClassificationResource.Classifications); LoadEvents(connection, events); } }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource = CycleDataResource.GetResource(meterDataSet, m_dbAdapterContainer); SagDataResource sagDataResource = SagDataResource.GetResource(meterDataSet, m_dbAdapterContainer); SwellDataResource swellDataResource = SwellDataResource.GetResource(meterDataSet, m_dbAdapterContainer); InterruptionDataResource interruptionDataResource = InterruptionDataResource.GetResource(meterDataSet, m_dbAdapterContainer); DisturbanceTableAdapter disturbanceAdapter = m_dbAdapterContainer.GetAdapter <DisturbanceTableAdapter>(); DisturbanceDataTable disturbanceTable = disturbanceAdapter.GetDataByFileGroup(meterDataSet.FileGroup.ID); SystemInfoDataContext systemInfo = m_dbAdapterContainer.GetAdapter <SystemInfoDataContext>(); m_disturbanceSeverityTable = new DisturbanceSeverityDataTable(); foreach (VoltageEnvelope envelope in systemInfo.VoltageEnvelopes) { foreach (DisturbanceRow disturbance in disturbanceTable) { IEnumerable <VoltageCurvePoint> points = envelope.VoltageCurves.Select(curve => curve.VoltageCurvePoints .Where(p => p.DurationSeconds <= disturbance.DurationSeconds) .OrderBy(p => p.LoadOrder) .LastOrDefault()); IEnumerable <int> severityCodes = points.Select(point => ((object)point != null) ? (int)((1.0D - disturbance.PerUnitMagnitude) / (1.0D - point.PerUnitMagnitude)) : 0); int maxSeverityCode = severityCodes .DefaultIfEmpty(0) .Max(); if (maxSeverityCode < 0) { maxSeverityCode = 0; } else if (maxSeverityCode > 5) { maxSeverityCode = 5; } m_disturbanceSeverityTable.AddDisturbanceSeverityRow(envelope.ID, disturbance.ID, maxSeverityCode); } } }
public void Initialize(MeterDataSet meterDataSet, DbAdapterContainer dbAdapterContainer) { DataGroup dataGroup; VICycleDataGroup viCycleDataGroup; CycleDataResource cycleDataResource; ConnectionStringParser.ParseConnectionString(meterDataSet.ConnectionString, this); m_disturbances = new Dictionary <DataGroup, List <Disturbance> >(); cycleDataResource = CycleDataResource.GetResource(meterDataSet, dbAdapterContainer); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { dataGroup = cycleDataResource.DataGroups[i]; viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; DetectDisturbances(dataGroup, viCycleDataGroup); } }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource; DataGroup dataGroup; VIDataGroup viDataGroup; VICycleDataGroup viCycleDataGroup; cycleDataResource = CycleDataResource.GetResource(meterDataSet, m_dbAdapterContainer); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { dataGroup = cycleDataResource.DataGroups[i]; viDataGroup = cycleDataResource.VIDataGroups[i]; viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; IdentifyBreakerOperations(dataGroup, viDataGroup, viCycleDataGroup); } m_meterDataSet = meterDataSet; }
public void Initialize(MeterDataSet meterDataSet) { ConnectionStringParser.ParseConnectionString(meterDataSet.ConnectionString, this); m_disturbances = new Dictionary <DataGroup, List <Disturbance> >(); CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); int lineCount = meterDataSet.Meter.MeterLines.Count; for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { DataGroup dataGroup = cycleDataResource.DataGroups[i]; VICycleDataGroup viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; Range <DateTime> eventDateRange = new Range <DateTime>(dataGroup.StartTime, dataGroup.EndTime); if (lineCount == 1 && dataGroup.Disturbances.Count > 0) { ProcessReportedDisturbances(meterDataSet.Meter, dataGroup); } else { DetectDisturbances(dataGroup, viCycleDataGroup); } } DataGroupsResource dataGroupsResource = meterDataSet.GetResource <DataGroupsResource>(); foreach (DataGroup dataGroup in dataGroupsResource.DataGroups) { if (dataGroup.DataSeries.Count > 0) { continue; } if (lineCount == 1 && dataGroup.Disturbances.Count > 0) { ProcessReportedDisturbances(meterDataSet.Meter, dataGroup); } } }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { TableOperations <BreakerChannel> breakerChannelTable = new TableOperations <BreakerChannel>(connection); List <int> channelsIDs = cycleDataResource.DataGroups .Where(dataGroup => dataGroup.Asset.AssetTypeID == (int)AssetType.Breaker) .SelectMany(dataGroup => dataGroup.DataSeries) .Select(dataSeries => dataSeries.SeriesInfo.ChannelID) .Distinct() .ToList(); // Look up the breaker numbers for the lines // that represent groupings of breaker current data m_breakerCurrents = new HashSet <string>(); if (channelsIDs.Count > 0) { m_breakerCurrents.UnionWith(breakerChannelTable .QueryRecordsWhere($"ChannelID IN ({string.Join(",", channelsIDs)})") .Select(breakerChannel => breakerChannel.BreakerNumber)); } FileGroup fileGroup = meterDataSet.FileGroup; for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { DataGroup dataGroup = cycleDataResource.DataGroups[i]; VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i]; VICycleDataGroup viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; IdentifyBreakerOperations(connection, fileGroup, dataGroup, viDataGroup, viCycleDataGroup); } } }
public override void Execute(MeterDataSet meterDataSet) { FaultDataResource faultDataResource = meterDataSet.GetResource <FaultDataResource>(); CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); FaultGroup faultGroup; Log.Info("Executing operation to load fault location data into the database..."); m_faultSummarizer = new FaultSummarizer(m_systemFrequency); m_faultSummarizer.MeterDataSet = meterDataSet; foreach (DataGroup dataGroup in cycleDataResource.DataGroups) { if (!faultDataResource.FaultLookup.TryGetValue(dataGroup, out faultGroup)) { continue; } // Generate summary rows for the fault to be entered into the database m_faultSummarizer.DataGroup = dataGroup; m_faultSummarizer.FaultGroup = faultGroup; m_faultSummarizer.SummarizeFault(); } }
public override void Execute(MeterDataSet meterDataSet) { CycleDataResource cycleDataResource = meterDataSet.GetResource <CycleDataResource>(); FaultDataResource faultDataResource = meterDataSet.GetResource <FaultDataResource>(); using (AdoDataConnection connection = meterDataSet.CreateDbConnection()) { object ToDateTime2(DateTime dateTime) { using (IDbCommand command = connection.Connection.CreateCommand()) { IDbDataParameter parameter = command.CreateParameter(); parameter.DbType = DbType.DateTime2; parameter.Value = dateTime; return(parameter); } } TableOperations <Event> eventTable = new TableOperations <Event>(connection); TableOperations <EventStat> eventStatTable = new TableOperations <EventStat>(connection); for (int i = 0; i < cycleDataResource.DataGroups.Count; i++) { const string Filter = "FileGroupID = {0} AND " + "AssetID = {1} AND " + "StartTime = {2} AND " + "EndTime = {3}"; DataGroup dataGroup = cycleDataResource.DataGroups[i]; VIDataGroup viDataGroup = cycleDataResource.VIDataGroups[i]; VICycleDataGroup viCycleDataGroup = cycleDataResource.VICycleDataGroups[i]; int fileGroupID = meterDataSet.FileGroup.ID; int assetID = dataGroup.Asset.ID; object startTime = ToDateTime2(dataGroup.StartTime); object endTime = ToDateTime2(dataGroup.EndTime); Event evt = eventTable.QueryRecordWhere(Filter, fileGroupID, assetID, startTime, endTime); if (evt == null) { continue; } double?vPeak = CalcVoltagePeak(viDataGroup); double?vaMax = CalcMax(viCycleDataGroup.VA?.RMS); double?vbMax = CalcMax(viCycleDataGroup.VB?.RMS); double?vcMax = CalcMax(viCycleDataGroup.VC?.RMS); double?vabMax = CalcMax(viCycleDataGroup.VAB?.RMS); double?vbcMax = CalcMax(viCycleDataGroup.VBC?.RMS); double?vcaMax = CalcMax(viCycleDataGroup.VCA?.RMS); double?vaMin = CalcMin(viCycleDataGroup.VA?.RMS); double?vbMin = CalcMin(viCycleDataGroup.VB?.RMS); double?vcMin = CalcMin(viCycleDataGroup.VC?.RMS); double?vabMin = CalcMin(viCycleDataGroup.VAB?.RMS); double?vbcMin = CalcMin(viCycleDataGroup.VBC?.RMS); double?vcaMin = CalcMin(viCycleDataGroup.VCA?.RMS); double?iPeak = CalcPeak(new[] { viDataGroup.IA, viDataGroup.IB, viDataGroup.IC }); double?iaMax = CalcMax(viCycleDataGroup.IA?.RMS); double?ibMax = CalcMax(viCycleDataGroup.IB?.RMS); double?icMax = CalcMax(viCycleDataGroup.IC?.RMS); double?ia2t = null; double?ib2t = null; double?ic2t = null; double?initialMW = CalcMW(viCycleDataGroup, true); double?finalMW = CalcMW(viCycleDataGroup, false); if (faultDataResource.FaultLookup.TryGetValue(dataGroup, out DataAnalysis.FaultGroup faultGroup)) { ia2t = CalcI2t(faultGroup, viDataGroup.IA); ib2t = CalcI2t(faultGroup, viDataGroup.IB); ic2t = CalcI2t(faultGroup, viDataGroup.IC); } int?pqviewID = null; if (meterDataSet.FilePath.Contains("\\pqview4\\events\\")) { Regex pattern = new Regex(@"^\\pqview4\\events\\PQView4 \d+\\\d+T\d+-(?<PQViewID>\d+).pqd$"); Match match = pattern.Match(meterDataSet.FilePath); string str = match.Groups["PQViewID"].Value; if (str != null) { pqviewID = int.Parse(str); } } eventStatTable.AddNewRecord(new EventStat() { EventID = evt.ID, VPeak = vPeak, VAMax = vaMax, VBMax = vbMax, VCMax = vcMax, VABMax = vabMax, VBCMax = vbcMax, VCAMax = vcaMax, VAMin = vaMin, VBMin = vbMin, VCMin = vcMin, VABMin = vabMin, VBCMin = vbcMin, VCAMin = vcaMin, IPeak = iPeak, IAMax = iaMax, IBMax = ibMax, ICMax = icMax, IA2t = ia2t, IB2t = ib2t, IC2t = ic2t, InitialMW = initialMW, FinalMW = finalMW, PQViewID = pqviewID }); } } }
private void Load() { CycleDataResource cycleDataResource = m_meterDataSet.GetResource <CycleDataResource>(); using (AdoDataConnection connection = m_meterDataSet.Meter.ConnectionFactory()) { TableOperations <Incident> incidentTable = new TableOperations <Incident>(connection); List <object> incidents = new List <object>(); foreach (DataGroup dg in cycleDataResource.DataGroups) { Incident incident = incidentTable.QueryRecordWhere("MeterID = {0} AND {1} Between StartTime AND EndTime", m_meterDataSet.Meter.ID, ToDateTime2(connection, dg.StartTime)); if (incident != null) { incidents.Add(incident.ID); } } if (!incidents.Any()) { return; } string formatString = string.Join(",", incidents.Select((id, index) => $"{{{index}}}")); connection.ExecuteNonQuery( $"WITH IMaxCycleData AS " + $"( " + $" SELECT " + $" *, " + $" CASE " + $" WHEN IARMS > IBRMS AND IARMS > ICRMS THEN IARMS " + $" WHEN IBRMS > ICRMS THEN IBRMS " + $" ELSE ICRMS " + $" END AS IMax " + $" FROM RotatedCycleData " + $"), MaxMin AS " + $"( " + $" SELECT " + $" IncidentID, " + $" MAX(IMax) AS IMax, " + $" MAX(IARMS) AS IAMax, " + $" MAX(IBRMS) AS IBMax, " + $" MAX(ICRMS) AS ICMax, " + $" MAX(IRRMS) AS IRMax, " + $" CASE WHEN MAX(VXARMS) > MAX(VYARMS) THEN MAX(VXARMS) ELSE MAX(VYARMS) END AS VAMax, " + $" CASE WHEN MAX(VXBRMS) > MAX(VYBRMS) THEN MAX(VXBRMS) ELSE MAX(VYBRMS) END AS VBMax, " + $" CASE WHEN MAX(VXCRMS) > MAX(VYCRMS) THEN MAX(VXCRMS) ELSE MAX(VYCRMS) END AS VCMax, " + $" CASE WHEN MIN(VXARMS) < MIN(VYARMS) THEN MIN(VXARMS) ELSE MIN(VYARMS) END AS VAMin, " + $" CASE WHEN MIN(VXBRMS) < MIN(VYBRMS) THEN MIN(VXBRMS) ELSE MIN(VYBRMS) END AS VBMin, " + $" CASE WHEN MIN(VXCRMS) < MIN(VYCRMS) THEN MIN(VXCRMS) ELSE MIN(VYCRMS) END AS VCMin " + $" FROM " + $" IMaxCycleData JOIN " + $" Event ON IMaxCycleData.EventID = Event.ID " + $" GROUP BY IncidentID " + $"), CycleDataFaultType AS " + $"( " + $" SELECT " + $" Event.IncidentID, " + $" ( " + $" SELECT TOP 1 FaultType " + $" FROM " + $" SOEPoint JOIN " + $" CycleData ON SOEPoint.CycleDataID = CycleData.ID JOIN " + $" Event InnerEvent ON CycleData.EventID = InnerEvent.ID " + $" WHERE " + $" InnerEvent.IncidentID = Event.IncidentID AND " + $" CycleData.Timestamp <= IMaxCycleData.Timestamp " + $" ORDER BY CycleData.Timestamp DESC " + $" ) AS FaultType, " + $" IMaxCycleData.IMax " + $" FROM " + $" IMaxCycleData JOIN " + $" Event ON IMaxCycleData.EventID = Event.ID " + $"), IncidentAttribute0 AS " + $"( " + $" SELECT " + $" MaxMin.IncidentID, " + $" ( " + $" SELECT TOP 1 FaultType " + $" FROM CycleDataFaultType " + $" WHERE " + $" MaxMin.IncidentID = CycleDataFaultType.IncidentID AND " + $" MaxMin.IMax = CycleDataFaultType.IMax " + $" ) AS FaultType, " + $" MaxMin.IAMax, " + $" MaxMin.IBMax, " + $" MaxMin.ICMax, " + $" MaxMin.IRMax, " + $" MaxMin.VAMax, " + $" MaxMin.VBMax, " + $" MaxMin.VCMax, " + $" MaxMin.VAMin, " + $" MaxMin.VBMin, " + $" MaxMin.VCMin " + $" FROM MaxMin " + $" WHERE MaxMin.IncidentID IN ({formatString}) " + $") " + $"MERGE INTO IncidentAttribute AS Target " + $"USING IncidentAttribute0 AS Source " + $"ON Source.IncidentID = Target.IncidentID " + $"WHEN MATCHED THEN " + $" UPDATE SET " + $" FaultType = Source.FaultType, " + $" IAMax = Source.IAMax, " + $" IBMax = Source.IBMax, " + $" ICMax = Source.ICMax, " + $" IRMax = Source.IRMax, " + $" VAMax = Source.VAMax, " + $" VBMax = Source.VBMax, " + $" VCMax = Source.VCMax, " + $" VAMin = Source.VAMin, " + $" VBMin = Source.VBMin, " + $" VCMin = Source.VCMin " + $"WHEN NOT MATCHED THEN " + $" INSERT (IncidentID, FaultType, IAMax, IBMax, ICMax, IRMax, VAMax, VBMax, VCMax, VAMin, VBMin, VCMin) " + $" VALUES (Source.IncidentID, Source.FaultType, Source.IAMax, Source.IBMax, Source.ICMax, Source.IRMax, Source.VAMax, Source.VBMax, Source.VCMax, Source.VAMin, Source.VBMin, Source.VCMin);", incidents.ToArray()); } }