private static void Migrate(string connectionString, string deviceDefinitionsFile) { LookupTables lookupTables; MeterLocation meterLocation; MeterLocation remoteMeterLocation; MeterLocationLine localLink; MeterLocationLine remoteLink; Meter meter; Line line; Series series; Channel channel; OutputChannel outputChannel; Dictionary <string, Tuple <Series, OutputChannel> > channelLookup; Tuple <Series, OutputChannel> tuple; string channelKey; int outputChannelIndex; LineImpedance lineImpedance; SourceImpedance localSourceImpedance; SourceImpedance remoteSourceImpedance; XDocument document = XDocument.Load(deviceDefinitionsFile); List <XElement> deviceElements = document.Elements().Elements("device").ToList(); XElement deviceAttributes; XElement impedancesElement; List <Tuple <Line, LineImpedance> > lineImpedances = new List <Tuple <Line, LineImpedance> >(); List <Tuple <MeterLocationLine, SourceImpedance> > sourceImpedances = new List <Tuple <MeterLocationLine, SourceImpedance> >(); List <Tuple <Series, OutputChannel> > outputChannels = new List <Tuple <Series, OutputChannel> >(); ProgressTracker progressTracker = new ProgressTracker(deviceElements.Count); using (MeterInfoDataContext meterInfo = new MeterInfoDataContext(connectionString)) using (FaultLocationInfoDataContext faultLocationInfo = new FaultLocationInfoDataContext(connectionString)) { // Load existing fault location configuration from the database progressTracker.StartPendingMessage("Loading existing fault location configuration from database..."); lookupTables = new LookupTables(meterInfo, faultLocationInfo); lookupTables.CreateLookups(document); progressTracker.EndPendingMessage(); // Load updates to fault location algorithms into the database progressTracker.StartPendingMessage("Loading updates to fault location algorithms into the database..."); foreach (XElement analyticsElement in document.Elements().Elements("analytics")) { LoadFaultLocationAlgorithms(analyticsElement, faultLocationInfo); } faultLocationInfo.SubmitChanges(); progressTracker.EndPendingMessage(); // Load updates to device configuration into the database progressTracker.WriteMessage(string.Format("Beginning migration of {0} device configurations...", deviceElements.Count)); foreach (XElement deviceElement in deviceElements) { lineImpedances.Clear(); sourceImpedances.Clear(); outputChannels.Clear(); // Get the element representing a device's attributes deviceAttributes = deviceElement.Element("attributes") ?? new XElement("attributes"); // Attempt to find existing configuration for this device and update the meter with any changes to the device's attributes meter = lookupTables.MeterLookup.GetOrAdd((string)deviceElement.Attribute("id"), assetKey => new Meter() { AssetKey = assetKey }); LoadMeterAttributes(meter, deviceAttributes); // Now that we know what meter we are processing, display a message to indicate that we are parsing this meter's configuration progressTracker.StartPendingMessage(string.Format("Loading configuration for meter {0} ({1})...", meter.Name, meter.AssetKey)); // Attempt to find existing configuration for the location of the meter and update with configuration changes meterLocation = lookupTables.MeterLocationLookup.GetOrAdd((string)deviceAttributes.Element("stationID"), assetKey => new MeterLocation() { AssetKey = assetKey }); LoadMeterLocationAttributes(meterLocation, deviceAttributes); // Link the meter location to the meter meter.MeterLocation = meterLocation; // Load updates to line configuration into the database foreach (XElement lineElement in deviceElement.Elements("lines").Elements("line")) { // Attempt to find existing configuration for the line and update with configuration changes line = lookupTables.LineLookup.GetOrAdd((string)lineElement.Attribute("id"), assetKey => new Line() { AssetKey = assetKey }); LoadLineAttributes(line, lineElement); // Provide a link between this line and the location housing the meter Link(meter, line, lineElement, lookupTables.MeterLineLookup); localLink = Link(meterLocation, line, lookupTables.MeterLocationLineLookup); if ((string)lineElement.Element("endStationID") != null) { // Attempt to find existing configuration for the location of the other end of the line and update with configuration changes remoteMeterLocation = lookupTables.MeterLocationLookup.GetOrAdd((string)lineElement.Element("endStationID"), assetKey => new MeterLocation() { AssetKey = assetKey }); LoadRemoteMeterLocationAttributes(remoteMeterLocation, lineElement); // Provide a link between this line and the remote location remoteLink = Link(remoteMeterLocation, line, lookupTables.MeterLocationLineLookup); } else { // Set remote meter location to null so we // know later that there isn't one defined remoteMeterLocation = null; remoteLink = null; } // Get a lookup table for the channels monitoring this line channelLookup = lookupTables.GetChannelLookup(meter, line); outputChannelIndex = 0; foreach (XElement channelElement in lineElement.Elements("channels").Elements()) { channelKey = channelElement.Name.LocalName; // Attempt to find an existing channel corresponding to this element if (channelLookup.TryGetValue(channelKey, out tuple)) { series = tuple.Item1; channel = series.Channel; outputChannel = tuple.Item2; } else { channel = new Channel(); series = new Series(); outputChannel = new OutputChannel(); channelLookup.Add(channelKey, Tuple.Create(series, outputChannel)); } // Load updates to channel configuration into the database LoadChannelAttributes(meter, line, remoteMeterLocation, channel, channelKey, lookupTables); LoadSeriesAttributes(channel, series, channelElement, lookupTables); outputChannel.ChannelKey = channelKey; outputChannel.LoadOrder = outputChannelIndex; outputChannels.Add(Tuple.Create(series, outputChannel)); outputChannelIndex++; } impedancesElement = lineElement.Element("impedances") ?? new XElement("impedances"); // Attempt to find existing impedance configuration for the line and update with configuration changes lineImpedance = lookupTables.LineImpedanceLookup.GetOrAdd(line, ln => new LineImpedance()); LoadLineImpedanceAttributes(lineImpedance, impedancesElement); lineImpedances.Add(Tuple.Create(line, lineImpedance)); // Attempt to find existing impedance configuration for the meter's location and update with configuration changes localSourceImpedance = lookupTables.SourceImpedanceLookup.GetOrAdd(localLink, location => new SourceImpedance()); LoadLocalSourceImpedanceAttributes(localSourceImpedance, impedancesElement); sourceImpedances.Add(Tuple.Create(localLink, localSourceImpedance)); if ((object)remoteLink != null) { // Attempt to find existing impedance configuration for the remote location and update with configuration changes remoteSourceImpedance = lookupTables.SourceImpedanceLookup.GetOrAdd(remoteLink, location => new SourceImpedance()); LoadRemoteSourceImpedanceAttributes(remoteSourceImpedance, impedancesElement); sourceImpedances.Add(Tuple.Create(remoteLink, remoteSourceImpedance)); } } if (meter.ID == 0) { meterInfo.Meters.InsertOnSubmit(meter); } meterInfo.SubmitChanges(); // Load updates to line impedance configuration into the database foreach (Tuple <Line, LineImpedance> mapping in lineImpedances) { line = mapping.Item1; lineImpedance = mapping.Item2; lineImpedance.LineID = line.ID; if (lineImpedance.ID == 0) { faultLocationInfo.LineImpedances.InsertOnSubmit(lineImpedance); } } // Load updates to source impedance configuration into the database foreach (Tuple <MeterLocationLine, SourceImpedance> mapping in sourceImpedances) { localLink = mapping.Item1; localSourceImpedance = mapping.Item2; localSourceImpedance.MeterLocationLineID = localLink.ID; if (localSourceImpedance.ID == 0 && (localSourceImpedance.RSrc != 0.0D || localSourceImpedance.XSrc != 0.0D)) { faultLocationInfo.SourceImpedances.InsertOnSubmit(localSourceImpedance); } } // Load updates to source impedance configuration into the database foreach (Tuple <Series, OutputChannel> mapping in outputChannels) { series = mapping.Item1; outputChannel = mapping.Item2; outputChannel.SeriesID = series.ID; if (outputChannel.ID == 0) { faultLocationInfo.OutputChannels.InsertOnSubmit(outputChannel); } } faultLocationInfo.SubmitChanges(); progressTracker.EndPendingMessage(); // Increment the progress counter progressTracker.MakeProgress(); } } }
private static void Migrate(string connectionString, string deviceDefinitionsFile) { LookupTables lookupTables; MeterLocation remoteMeterLocation; Meter meter; Line line; Series series; Channel channel; XDocument document = XDocument.Load(deviceDefinitionsFile); Dictionary <string, XElement> deviceLookup = document.Elements().Elements("device").ToDictionary(device => (string)device.Attribute("id")); List <XElement> deviceElements; XElement deviceAttributes; Dictionary <string, Channel> channelLookup; ProgressTracker progressTracker = new ProgressTracker(deviceLookup.Count * 2); deviceElements = deviceLookup.Values.OrderBy(device => { int count = 0; while (deviceLookup.TryGetValue((string)device.Element("parent") ?? string.Empty, out device)) { count++; } return(count); }).ToList(); using (AdoDataConnection connection = new AdoDataConnection(connectionString, "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.SqlClient.SqlConnection; AdapterType=System.Data.SqlClient.SqlDataAdapter")) { // Load existing configuration from the database progressTracker.StartPendingMessage("Loading existing configuration from database..."); lookupTables = new LookupTables(); lookupTables.CreateLookups(document, connection); progressTracker.EndPendingMessage(); // Load updates to device configuration into the database progressTracker.WriteMessage($"Beginning migration of {deviceElements.Count} device configurations..."); foreach (XElement deviceElement in deviceElements) { // Get the element representing a device's attributes deviceAttributes = deviceElement.Element("attributes") ?? new XElement("attributes"); // Attempt to find existing configuration for this device and update the meter with any changes to the device's attributes meter = LoadMeterAttributes(lookupTables, deviceElement, deviceAttributes, connection); // Now that we know what meter we are processing, display a message to indicate that we are parsing this meter's configuration progressTracker.StartPendingMessage($"Loading configuration for meter {meter.Name} ({meter.AssetKey})..."); // Load updates to line configuration into the database foreach (XElement lineElement in deviceElement.Elements("lines").Elements("line")) { // Attempt to find existing configuration for the line and update with configuration changes line = LoadLineAttributes(lookupTables, lineElement, connection); // Provide a link between this line and the location housing the meter Link(meter.ID, line.ID, lineElement, connection); Link(lookupTables.MeterLocationLookup.GetOrDefault((string)deviceAttributes.Element("stationID")).ID, line.ID, connection); if ((string)lineElement.Element("endStationID") != null) { // Attempt to find existing configuration for the location of the other end of the line and update with configuration changes remoteMeterLocation = LoadRemoteMeterLocationAttributes(lookupTables, lineElement, connection); // Provide a link between this line and the remote location Link(remoteMeterLocation.ID, line.ID, connection); } // Get a lookup table for the channels monitoring this line channelLookup = lookupTables.GetChannelLookup(meter, line, connection); foreach (string channelName in new[] { "VX1", "VX2", "VX3", "VY1", "VY2", "VY3", "I1", "I2", "I3" }) { if (channelLookup.ContainsKey(channelName)) { continue; } channel = new Channel(); series = new Series(); channelLookup.Add(channelName, channel); // Load updates to channel configuration into the database LoadChannelAttributes(meter, line, channel, channelName, lookupTables, connection); LoadSeriesAttributes(channel, series, lookupTables, connection); } } progressTracker.EndPendingMessage(); // Increment the progress counter progressTracker.MakeProgress(); } foreach (XElement deviceElement in deviceElements) { // Get the element representing a device's attributes deviceAttributes = deviceElement.Element("attributes") ?? new XElement("attributes"); meter = lookupTables.MeterLookup.GetOrDefault((string)deviceElement.Attribute("id")); if ((string)deviceAttributes.Element("parentNormal") != null && lookupTables.MeterLookup.ContainsKey((string)deviceAttributes.Element("parentNormal"))) { meter.ParentNormalID = lookupTables.MeterLookup.GetOrDefault((string)deviceAttributes.Element("parentNormal")).ID; } if ((string)deviceAttributes.Element("parentAlternate") != null && (string)deviceAttributes.Element("parentAlternate") != "none" && lookupTables.MeterLookup.ContainsKey((string)deviceAttributes.Element("parentAlternate"))) { meter.ParentAlternateID = lookupTables.MeterLookup.GetOrDefault((string)deviceAttributes.Element("parentAlternate")).ID; } (new TableOperations <Meter>(connection)).UpdateRecord(meter); // Now that we know what meter we are processing, display a message to indicate that we are parsing this meter's configuration progressTracker.StartPendingMessage($"Loading parent configuration for meter {meter.Name} ({meter.AssetKey})..."); progressTracker.EndPendingMessage(); // Increment the progress counter progressTracker.MakeProgress(); } } }