Пример #1
0
        public void Run()
        {
            // check arguments
            if (string.IsNullOrEmpty(_args.InputFilename))
            {
                throw new ApplicationException(DacChkSumResource.ErrorNoInputFile);
            }

            var inputFile = new FileInfo(_args.InputFilename);
            if (!inputFile.Exists)
            {
                throw new FileNotFoundException(_args.InputFilename);
            }

            if (!DacPackage.IsDacPac(inputFile))
            {
                throw new FileFormatException(DacChkSumResource.ErrorNotValidDacPac);
            }

            if (_args.Verbose)
            {
                Console.Out.WriteLine("Starting:  [{0}]", DateTime.Now);
                Console.Out.WriteLine("Input:     [{0}]", inputFile.FullName);
                Console.Out.WriteLine("Update:    [{0}]", this._args.Update.ToString(CultureInfo.InvariantCulture));
            }

            using (var package = new DacPackage(inputFile))
            {
                package.Open();

                byte[] oldChkSum = package.ReadChecksum();
                byte[] newChkSum = package.CalculateChecksum();

                Console.Out.WriteLine("Model checksum");
                Console.Out.WriteLine("Stored:   :[{0}]", DacPackage.ByteArrayToString(oldChkSum));
                Console.Out.WriteLine("Calculated:[{0}]", DacPackage.ByteArrayToString(newChkSum));

                if ((_args.Update) && (!System.Linq.Enumerable.SequenceEqual(oldChkSum, newChkSum)))
                {
                    Console.Out.WriteLine("Updating checksum");
                    package.UpdateChecksum(newChkSum);
                    package.Save();
                }

                package.Close();
            }

            if (_args.Verbose)
            {
                Console.Out.WriteLine("Finished:  [{0}]", DateTime.Now);
            }
        }
Пример #2
0
        internal static bool Merge(FileInfo inputFile, FileInfo outputFile, DirectoryInfo referenceLoadPath)
        {
            bool singleFileMode = (outputFile == null);

            using (var inputPackage = new DacPackage(inputFile))
            {
                inputPackage.Open(singleFileMode ? FileAccess.ReadWrite : FileAccess.Read);

                var inputModelDoc = inputPackage.Model;
                if (inputModelDoc.Root == null)
                {
                    throw new NullReferenceException("inputModelDoc");
                }

                LogWriter.WriteMessage(String.Format(DacMergeResource.LoadingFile, inputFile.Name));

                // TODO:<GertD> check if this is needed
                // set to last model element in input document
                var inputModelElement = inputModelDoc.Root.Elements().LastOrDefault(e => e.Name.LocalName == Constants.ModelElement);
                if (inputModelElement == null)
                {
                    throw new NullReferenceException(Constants.ModelElement);
                }

                // Event handder to record all the changes to the model
                inputModelElement.Changed += new EventHandler<XObjectChangeEventArgs>
                    ((sender, e) =>
                        {
                            var element = sender as XElement;
                            if (element != null)
                            {
                                var elementType = Constants.Unknown;
                                var attribute = element.Attribute(Constants.TypeAttribute);
                                if (attribute != null)
                                    elementType = element.Attribute(Constants.TypeAttribute).Value;

                                var elementName = Constants.Unnamed;
                                attribute = element.Attribute(Constants.NameAttribute);
                                if (attribute != null)
                                    elementName = element.Attribute(Constants.NameAttribute).Value;

                                LogWriter.WriteMessage(
                                    String.Format("{0} - {1} - {2}",
                                    e.ObjectChange,
                                    elementType,
                                    elementName));
                            }
                        }
                    );

                // get child packages, using the CustomData Category="Reference" and Type="SqlSchema"
                //
                // <CustomData Category="Reference" Type="SqlSchema">
                //    <Metadata Value="D:\USERS\GERTD\PROJECTS\DACMERGE\CHILDDB1\BIN\DEBUG\CHILDDB1.DACPAC" Name="FileName"/>
                //    <Metadata Value="ChildDB1.dacpac" Name="LogicalName"/>
                //    <Metadata Value="False" Name="SuppressMissingDependenciesErrors"/>
                //    <Metadata Value="[$(OtherServer)].[$(ChildDB1)]" Name="ExternalParts"/>
                // </CustomData>
                var header = inputModelDoc.Root.Elements()
                    .Where(e => e.Name.LocalName == Constants.HeaderElement);

                var customDataElements = header.Elements()
                    .Where(e => e.Name.LocalName == Constants.CustomData)
                    .Where(a => a.Attribute(Constants.CategoryAttribute).Value == Constants.Reference)
                    .Where(a => a.Attribute(Constants.TypeAttribute).Value == Constants.SqlSchema);

                Int32 maxDisambiguator = 0;
                var x = inputModelElement.Descendants()
                    .Where(e => e.Name.LocalName == Constants.AnnotationElement)
                    .Where(a =>
                    {
                        var attribute = a.Attribute(Constants.DisambiguatorAttribute);
                        return attribute != null;
                    })
                    .LastOrDefault().Attribute(Constants.DisambiguatorAttribute).Value;

                Int32.TryParse((String.IsNullOrEmpty(x) ? "3" : x), out maxDisambiguator);

                Int32 maxCummulativeDisambiguator = maxDisambiguator;

                foreach (var customDataElement in customDataElements.ToList())
                {
                    var inSameDb = String.IsNullOrEmpty(customDataElement.Elements()
                        .Where(e => e.Name.LocalName == Constants.Metadata)
                        .Where(a => a.Attribute(Constants.NameAttribute).Value == Constants.ExternalParts)
                        .Select(a => a.Attribute(Constants.ValueAttribute).Value).FirstOrDefault());

                    if (inSameDb)
                    {
                        // get dacpac filename
                        var childDacPac = customDataElement.Elements()
                            .Where(e => e.Name.LocalName == Constants.Metadata)
                            .Where(a => a.Attribute(Constants.NameAttribute).Value == Constants.FileName)
                            .Select(a => a.Attribute(Constants.ValueAttribute).Value).FirstOrDefault();

                        if (childDacPac == null || String.IsNullOrEmpty(childDacPac))
                        {
                            throw new ArgumentNullException("childDacPac");
                        }

                        var childFile = ResolveFileName(childDacPac, inputFile, referenceLoadPath);
                        if (childFile == null)
                        {
                            throw new ArgumentNullException("childFile");
                        }

                        if (!childFile.Exists)
                        {
                            throw new FileNotFoundException(childDacPac);
                        }

                        LogWriter.WriteMessage(String.Format(DacMergeResource.MergeFile, childFile.Name));

                        // import child package
                        using (var childPackage = new DacPackage(childFile))
                        {
                            childPackage.Open(FileAccess.Read);

                            // var childModelPart = childPackage.GetPart(modelPartUri);

                            var childModelDoc = childPackage.Model; // XDocument.Load(XmlReader.Create(childModelPart.GetStream()));
                            if (childModelDoc.Root == null)
                            {
                                throw new NullReferenceException("childModelDoc");
                            }

                            var childModelElement = childModelDoc.Root.Elements().FirstOrDefault(e => e.Name.LocalName == Constants.ModelElement);
                            if (childModelElement == null)
                            {
                                throw new NullReferenceException(Constants.ModelElement);
                            }

                            // remove DatabaseOptions from child model
                            RemoveElements(childModelElement, Constants.TypeAttribute, SqlElementType.SqlDatabaseOptions);

                            // update Disambiguator for Annotations
                            var annotations = childModelElement.Descendants()
                                .Where(e => e.Name.LocalName == Constants.AnnotationElement)
                                .Where(a =>
                                {
                                    var attribute = a.Attribute(Constants.DisambiguatorAttribute);
                                    return attribute != null;
                                });

                            foreach (var annotation in annotations)
                            {
                                Int32 disambiguator = 0;

                                if (Int32.TryParse(annotation.Attribute(Constants.DisambiguatorAttribute).Value, out disambiguator))
                                {
                                    Int32 newdisambiguator = disambiguator + maxDisambiguator;
                                    annotation.Attribute(Constants.DisambiguatorAttribute).Value = newdisambiguator.ToString(CultureInfo.InvariantCulture);
                                    maxCummulativeDisambiguator = Math.Max(newdisambiguator, maxCummulativeDisambiguator);
                                }
                                else
                                {
                                    System.Diagnostics.Debug.Assert(false);
                                }
                            }

                            // update Disambiguator for AttachedAnnotations
                            var attachedAnnotations = childModelElement.Descendants()
                                .Where(e => e.Name.LocalName == Constants.AttachedAnnotationElement)
                                .Where(a =>
                                {
                                    var attribute = a.Attribute(Constants.DisambiguatorAttribute);
                                    return attribute != null;
                                });

                            foreach (var attachedAnnotation in attachedAnnotations)
                            {
                                Int32 disambiguator = 0;
                                if (Int32.TryParse(attachedAnnotation.Attribute(Constants.DisambiguatorAttribute).Value, out disambiguator))
                                {
                                    Int32 newdisambiguator = disambiguator + maxDisambiguator;
                                    attachedAnnotation.Attribute(Constants.DisambiguatorAttribute).Value = newdisambiguator.ToString(CultureInfo.InvariantCulture);
                                }
                                else
                                {
                                    System.Diagnostics.Debug.Assert(false);
                                }
                            }

                            var childElements = childModelElement.Elements();

                            LogWriter.WriteMessage(String.Format(DacMergeResource.MergeModelElements, childElements.Count()));

                            inputModelElement.Add(childElements);

                            maxDisambiguator = maxCummulativeDisambiguator;

                            customDataElement.Remove();

                        }
                    }
                }

                DacPackage outputPackage = null;
                if (singleFileMode)
                {
                    outputPackage = inputPackage;
                }
                else
                {
                    outputPackage = new DacPackage(outputFile);
                    outputPackage.Open(FileAccess.ReadWrite);
                }

                if (singleFileMode)
                {
                    LogWriter.WriteMessage(String.Format(DacMergeResource.Stream, DacPackage.ModelUri));
                    inputModelDoc.Save(outputPackage.GetStream(DacPackage.ModelUri));
                }
                else
                {
                    LogWriter.WriteMessage(DacMergeResource.CopyingStreams);

                    // copy all parts from input to output package,
                    // except for the model.xml stream which will is replace with the merged XML document content
                    foreach (var part in inputPackage.GetParts())
                    {
                        LogWriter.WriteMessage(String.Format(DacMergeResource.Stream, part.Uri));

                        var outputPart = outputPackage.CreatePartAs(part);

                        if (part.Uri == DacPackage.ModelUri)
                        {
                            inputModelDoc.Save(outputPart.GetStream());
                        }
                        else
                        {
                            if (outputPart == null)
                                throw new NullReferenceException("outputPart");

                            part.GetStream().CopyTo(outputPart.GetStream());
                        }
                    }
                }

                var outputOriginDoc = XDocument.Load(XmlReader.Create(outputPackage.GetStream(DacPackage.OriginUri)));
                if (outputOriginDoc.Root == null)
                {
                    throw new NullReferenceException("outputOriginDoc");
                }

                LogWriter.WriteMessage(DacMergeResource.CalculatingChecksum);
                var newChecksum = outputPackage.CalculateChecksum();
                LogWriter.WriteMessage(DacPackage.ByteArrayToString(newChecksum));

                LogWriter.WriteMessage(DacMergeResource.UpdatingChecksum);
                outputPackage.UpdateChecksum(newChecksum);

                outputOriginDoc.Save(outputPackage.GetStream(DacPackage.OriginUri));

                outputPackage.Close();
                inputPackage.Close();
            }

            return true;
        }