1 //--------------------------------------------------------------------- 2 // <copyright file="MetadataMappingHasherVisitor.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 6 // @owner Microsoft 7 // @backupOwner Microsoft 8 //--------------------------------------------------------------------- 9 10 using System; 11 using System.Collections.Generic; 12 using System.Linq; 13 using System.Text; 14 using System.Data.Metadata.Edm; 15 using System.Data.Common; 16 using System.Data.Common.Utils; 17 using System.Data.Mapping; 18 using System.Diagnostics; 19 using System.Globalization; 20 21 22 namespace System.Data.Mapping 23 { 24 internal partial class MetadataMappingHasherVisitor : BaseMetadataMappingVisitor 25 { 26 private CompressingHashBuilder m_hashSourceBuilder; 27 private Dictionary<Object, int> m_itemsAlreadySeen = new Dictionary<Object, int>(); 28 private int m_instanceNumber = 0; 29 private EdmItemCollection m_EdmItemCollection; 30 private double m_EdmVersion; 31 private double m_MappingVersion; 32 MetadataMappingHasherVisitor(double mappingVersion)33 private MetadataMappingHasherVisitor(double mappingVersion) 34 { 35 m_MappingVersion = mappingVersion; 36 this.m_hashSourceBuilder = new CompressingHashBuilder(MetadataHelper.CreateMetadataHashAlgorithm(m_MappingVersion)); 37 } 38 39 #region visitor method Visit(StorageEntityContainerMapping storageEntityContainerMapping)40 protected override void Visit(StorageEntityContainerMapping storageEntityContainerMapping) 41 { 42 Debug.Assert(storageEntityContainerMapping != null, "storageEntityContainerMapping cannot be null!"); 43 44 // at the entry point of visitor, we setup the versions 45 Debug.Assert(m_MappingVersion == storageEntityContainerMapping.StorageMappingItemCollection.MappingVersion, "the original version and the mapping collection version are not the same"); 46 this.m_MappingVersion = storageEntityContainerMapping.StorageMappingItemCollection.MappingVersion; 47 this.m_EdmVersion = storageEntityContainerMapping.StorageMappingItemCollection.EdmItemCollection.EdmVersion; 48 49 this.m_EdmItemCollection = storageEntityContainerMapping.StorageMappingItemCollection.EdmItemCollection; 50 51 int index; 52 if (!this.AddObjectToSeenListAndHashBuilder(storageEntityContainerMapping, out index)) 53 { 54 // if this has been add to the seen list, then just 55 return; 56 } 57 if (this.m_itemsAlreadySeen.Count > 1) 58 { 59 60 // this means user try another visit over SECM, this is allowed but all the previous visit all lost due to clean 61 // user can visit different SECM objects by using the same visitor to load the SECM object 62 this.Clean(); 63 Visit(storageEntityContainerMapping); 64 return; 65 } 66 67 this.AddObjectStartDumpToHashBuilder(storageEntityContainerMapping, index); 68 69 #region Inner data visit 70 71 this.AddObjectContentToHashBuilder(storageEntityContainerMapping.Identity); 72 73 this.AddV2ObjectContentToHashBuilder(storageEntityContainerMapping.GenerateUpdateViews, this.m_MappingVersion); 74 75 base.Visit(storageEntityContainerMapping); 76 77 #endregion 78 79 this.AddObjectEndDumpToHashBuilder(); 80 } 81 Visit(EntityContainer entityContainer)82 protected override void Visit(EntityContainer entityContainer) 83 { 84 int index; 85 if (!this.AddObjectToSeenListAndHashBuilder(entityContainer, out index)) 86 { 87 return; 88 } 89 90 this.AddObjectStartDumpToHashBuilder(entityContainer, index); 91 92 #region Inner data visit 93 94 this.AddObjectContentToHashBuilder(entityContainer.Identity); 95 // Name is covered by Identity 96 97 base.Visit(entityContainer); 98 99 #endregion 100 101 this.AddObjectEndDumpToHashBuilder(); 102 } 103 Visit(StorageSetMapping storageSetMapping)104 protected override void Visit(StorageSetMapping storageSetMapping) 105 { 106 int index; 107 if (!this.AddObjectToSeenListAndHashBuilder(storageSetMapping, out index)) 108 { 109 return; 110 } 111 112 this.AddObjectStartDumpToHashBuilder(storageSetMapping, index); 113 114 #region Inner data visit 115 base.Visit(storageSetMapping); 116 #endregion 117 118 this.AddObjectEndDumpToHashBuilder(); 119 } 120 Visit(StorageTypeMapping storageTypeMapping)121 protected override void Visit(StorageTypeMapping storageTypeMapping) 122 { 123 int index; 124 if (!this.AddObjectToSeenListAndHashBuilder(storageTypeMapping, out index)) 125 { 126 return; 127 } 128 129 this.AddObjectStartDumpToHashBuilder(storageTypeMapping, index); 130 131 #region Inner data visit 132 133 base.Visit(storageTypeMapping); 134 135 #endregion 136 137 this.AddObjectEndDumpToHashBuilder(); 138 } 139 Visit(StorageMappingFragment storageMappingFragment)140 protected override void Visit(StorageMappingFragment storageMappingFragment) 141 { 142 int index; 143 if (!this.AddObjectToSeenListAndHashBuilder(storageMappingFragment, out index)) 144 { 145 return; 146 } 147 148 this.AddObjectStartDumpToHashBuilder(storageMappingFragment, index); 149 150 #region Inner data visit 151 152 this.AddV2ObjectContentToHashBuilder(storageMappingFragment.IsSQueryDistinct, this.m_MappingVersion); 153 154 base.Visit(storageMappingFragment); 155 156 #endregion 157 158 this.AddObjectEndDumpToHashBuilder(); 159 } 160 Visit(StoragePropertyMapping storagePropertyMapping)161 protected override void Visit(StoragePropertyMapping storagePropertyMapping) 162 { 163 base.Visit(storagePropertyMapping); 164 } 165 Visit(StorageComplexPropertyMapping storageComplexPropertyMapping)166 protected override void Visit(StorageComplexPropertyMapping storageComplexPropertyMapping) 167 { 168 int index; 169 if (!this.AddObjectToSeenListAndHashBuilder(storageComplexPropertyMapping, out index)) 170 { 171 return; 172 } 173 174 this.AddObjectStartDumpToHashBuilder(storageComplexPropertyMapping, index); 175 176 #region Inner data visit 177 178 base.Visit(storageComplexPropertyMapping); 179 180 #endregion 181 182 this.AddObjectEndDumpToHashBuilder(); 183 } Visit(StorageComplexTypeMapping storageComplexTypeMapping)184 protected override void Visit(StorageComplexTypeMapping storageComplexTypeMapping) 185 { 186 int index; 187 if (!this.AddObjectToSeenListAndHashBuilder(storageComplexTypeMapping, out index)) 188 { 189 return; 190 } 191 192 this.AddObjectStartDumpToHashBuilder(storageComplexTypeMapping, index); 193 194 #region Inner data visit 195 196 base.Visit(storageComplexTypeMapping); 197 198 #endregion 199 200 this.AddObjectEndDumpToHashBuilder(); 201 } 202 Visit(StorageConditionPropertyMapping storageConditionPropertyMapping)203 protected override void Visit(StorageConditionPropertyMapping storageConditionPropertyMapping) 204 { 205 int index; 206 if (!this.AddObjectToSeenListAndHashBuilder(storageConditionPropertyMapping, out index)) 207 { 208 return; 209 } 210 211 this.AddObjectStartDumpToHashBuilder(storageConditionPropertyMapping, index); 212 213 #region Inner data visit 214 this.AddObjectContentToHashBuilder(storageConditionPropertyMapping.IsNull); 215 this.AddObjectContentToHashBuilder(storageConditionPropertyMapping.Value); 216 217 base.Visit(storageConditionPropertyMapping); 218 219 #endregion 220 221 this.AddObjectEndDumpToHashBuilder(); 222 } 223 Visit(StorageScalarPropertyMapping storageScalarPropertyMapping)224 protected override void Visit(StorageScalarPropertyMapping storageScalarPropertyMapping) 225 { 226 int index; 227 if (!this.AddObjectToSeenListAndHashBuilder(storageScalarPropertyMapping, out index)) 228 { 229 return; 230 } 231 232 this.AddObjectStartDumpToHashBuilder(storageScalarPropertyMapping, index); 233 234 #region Inner data visit 235 236 base.Visit(storageScalarPropertyMapping); 237 238 #endregion 239 240 this.AddObjectEndDumpToHashBuilder(); 241 } 242 Visit(EntitySetBase entitySetBase)243 protected override void Visit(EntitySetBase entitySetBase) 244 { 245 base.Visit(entitySetBase); 246 } 247 Visit(EntitySet entitySet)248 protected override void Visit(EntitySet entitySet) 249 { 250 int index; 251 if (!this.AddObjectToSeenListAndHashBuilder(entitySet, out index)) 252 { 253 return; 254 } 255 #region Inner data visit 256 257 this.AddObjectStartDumpToHashBuilder(entitySet, index); 258 this.AddObjectContentToHashBuilder(entitySet.Name); 259 this.AddObjectContentToHashBuilder(entitySet.Schema); 260 this.AddObjectContentToHashBuilder(entitySet.Table); 261 262 base.Visit(entitySet); 263 264 foreach (var entityType in MetadataHelper.GetTypeAndSubtypesOf(entitySet.ElementType, this.m_EdmItemCollection, false).Where(type => type != entitySet.ElementType)) 265 { 266 this.Visit(entityType); 267 } 268 269 #endregion 270 271 this.AddObjectEndDumpToHashBuilder(); 272 } 273 Visit(AssociationSet associationSet)274 protected override void Visit(AssociationSet associationSet) 275 { 276 int index; 277 if (!this.AddObjectToSeenListAndHashBuilder(associationSet, out index)) 278 { 279 return; 280 } 281 282 this.AddObjectStartDumpToHashBuilder(associationSet, index); 283 284 #region Inner data visit 285 this.AddObjectContentToHashBuilder(associationSet.CachedProviderSql); 286 // Name is coverd by Identity 287 this.AddObjectContentToHashBuilder(associationSet.Identity); 288 this.AddObjectContentToHashBuilder(associationSet.Schema); 289 this.AddObjectContentToHashBuilder(associationSet.Table); 290 291 base.Visit(associationSet); 292 293 #endregion 294 295 this.AddObjectEndDumpToHashBuilder(); 296 } 297 Visit(EntityType entityType)298 protected override void Visit(EntityType entityType) 299 { 300 int index; 301 if (!this.AddObjectToSeenListAndHashBuilder(entityType, out index)) 302 { 303 return; 304 } 305 306 this.AddObjectStartDumpToHashBuilder(entityType, index); 307 308 #region Inner data visit 309 this.AddObjectContentToHashBuilder(entityType.Abstract); 310 this.AddObjectContentToHashBuilder(entityType.Identity); 311 // FullName, Namespace and Name are all covered by Identity 312 313 base.Visit(entityType); 314 315 #endregion 316 317 this.AddObjectEndDumpToHashBuilder(); 318 } 319 Visit(AssociationSetEnd associationSetEnd)320 protected override void Visit(AssociationSetEnd associationSetEnd) 321 { 322 int index; 323 if (!this.AddObjectToSeenListAndHashBuilder(associationSetEnd, out index)) 324 { 325 return; 326 } 327 328 this.AddObjectStartDumpToHashBuilder(associationSetEnd, index); 329 330 #region Inner data visit 331 this.AddObjectContentToHashBuilder(associationSetEnd.Identity); 332 // Name is covered by Identity 333 334 base.Visit(associationSetEnd); 335 336 #endregion 337 338 this.AddObjectEndDumpToHashBuilder(); 339 } 340 Visit(AssociationType associationType)341 protected override void Visit(AssociationType associationType) 342 { 343 int index; 344 if (!this.AddObjectToSeenListAndHashBuilder(associationType, out index)) 345 { 346 return; 347 } 348 349 this.AddObjectStartDumpToHashBuilder(associationType, index); 350 351 #region Inner data visit 352 this.AddObjectContentToHashBuilder(associationType.Abstract); 353 this.AddObjectContentToHashBuilder(associationType.Identity); 354 // FullName, Namespace, and Name are all covered by Identity 355 356 base.Visit(associationType); 357 358 #endregion 359 360 this.AddObjectEndDumpToHashBuilder(); 361 } 362 Visit(EdmProperty edmProperty)363 protected override void Visit(EdmProperty edmProperty) 364 { 365 int index; 366 if (!this.AddObjectToSeenListAndHashBuilder(edmProperty, out index)) 367 { 368 return; 369 } 370 371 this.AddObjectStartDumpToHashBuilder(edmProperty, index); 372 373 #region Inner data visit 374 // since the delaring type is fixed and referenced to the upper type, 375 // there is no need to hash this 376 //this.AddObjectContentToHashBuilder(edmProperty.DeclaringType); 377 this.AddObjectContentToHashBuilder(edmProperty.DefaultValue); 378 this.AddObjectContentToHashBuilder(edmProperty.Identity); 379 // Name is covered by Identity 380 this.AddObjectContentToHashBuilder(edmProperty.IsStoreGeneratedComputed); 381 this.AddObjectContentToHashBuilder(edmProperty.IsStoreGeneratedIdentity); 382 this.AddObjectContentToHashBuilder(edmProperty.Nullable); 383 384 base.Visit(edmProperty); 385 386 #endregion 387 388 this.AddObjectEndDumpToHashBuilder(); 389 } 390 Visit(NavigationProperty navigationProperty)391 protected override void Visit(NavigationProperty navigationProperty) 392 { 393 // navigation properties are not considered in view generation 394 return; 395 } 396 Visit(EdmMember edmMember)397 protected override void Visit(EdmMember edmMember) 398 { 399 int index; 400 if (!this.AddObjectToSeenListAndHashBuilder(edmMember, out index)) 401 { 402 return; 403 } 404 405 this.AddObjectStartDumpToHashBuilder(edmMember, index); 406 407 #region Inner data visit 408 this.AddObjectContentToHashBuilder(edmMember.Identity); 409 // Name is covered by Identity 410 this.AddObjectContentToHashBuilder(edmMember.IsStoreGeneratedComputed); 411 this.AddObjectContentToHashBuilder(edmMember.IsStoreGeneratedIdentity); 412 413 base.Visit(edmMember); 414 415 #endregion 416 417 this.AddObjectEndDumpToHashBuilder(); 418 } 419 Visit(AssociationEndMember associationEndMember)420 protected override void Visit(AssociationEndMember associationEndMember) 421 { 422 int index; 423 if (!this.AddObjectToSeenListAndHashBuilder(associationEndMember, out index)) 424 { 425 return; 426 } 427 428 this.AddObjectStartDumpToHashBuilder(associationEndMember, index); 429 430 #region Inner data visit 431 this.AddObjectContentToHashBuilder(associationEndMember.DeleteBehavior); 432 this.AddObjectContentToHashBuilder(associationEndMember.Identity); 433 // Name is covered by Identity 434 this.AddObjectContentToHashBuilder(associationEndMember.IsStoreGeneratedComputed); 435 this.AddObjectContentToHashBuilder(associationEndMember.IsStoreGeneratedIdentity); 436 this.AddObjectContentToHashBuilder(associationEndMember.RelationshipMultiplicity); 437 438 base.Visit(associationEndMember); 439 440 #endregion 441 442 this.AddObjectEndDumpToHashBuilder(); 443 } 444 Visit(ReferentialConstraint referentialConstraint)445 protected override void Visit(ReferentialConstraint referentialConstraint) 446 { 447 int index; 448 if (!this.AddObjectToSeenListAndHashBuilder(referentialConstraint, out index)) 449 { 450 return; 451 } 452 453 this.AddObjectStartDumpToHashBuilder(referentialConstraint, index); 454 455 #region Inner data visit 456 this.AddObjectContentToHashBuilder(referentialConstraint.Identity); 457 458 base.Visit(referentialConstraint); 459 460 #endregion 461 462 this.AddObjectEndDumpToHashBuilder(); 463 } 464 Visit(RelationshipEndMember relationshipEndMember)465 protected override void Visit(RelationshipEndMember relationshipEndMember) 466 { 467 int index; 468 if (!this.AddObjectToSeenListAndHashBuilder(relationshipEndMember, out index)) 469 { 470 return; 471 } 472 473 this.AddObjectStartDumpToHashBuilder(relationshipEndMember, index); 474 475 #region Inner data visit 476 this.AddObjectContentToHashBuilder(relationshipEndMember.DeleteBehavior); 477 this.AddObjectContentToHashBuilder(relationshipEndMember.Identity); 478 // Name is covered by Identity 479 this.AddObjectContentToHashBuilder(relationshipEndMember.IsStoreGeneratedComputed); 480 this.AddObjectContentToHashBuilder(relationshipEndMember.IsStoreGeneratedIdentity); 481 this.AddObjectContentToHashBuilder(relationshipEndMember.RelationshipMultiplicity); 482 483 base.Visit(relationshipEndMember); 484 485 #endregion 486 487 this.AddObjectEndDumpToHashBuilder(); 488 } 489 Visit(TypeUsage typeUsage)490 protected override void Visit(TypeUsage typeUsage) 491 { 492 int index; 493 if (!this.AddObjectToSeenListAndHashBuilder(typeUsage, out index)) 494 { 495 return; 496 } 497 498 this.AddObjectStartDumpToHashBuilder(typeUsage, index); 499 500 #region Inner data visit 501 //No need to add identity of TypeUsage to the hash since it would take into account 502 //facets that viewgen would not care and we visit the important facets anyway. 503 504 base.Visit(typeUsage); 505 506 #endregion 507 508 this.AddObjectEndDumpToHashBuilder(); 509 } 510 Visit(RelationshipType relationshipType)511 protected override void Visit(RelationshipType relationshipType) 512 { 513 base.Visit(relationshipType); 514 } 515 Visit(EdmType edmType)516 protected override void Visit(EdmType edmType) 517 { 518 base.Visit(edmType); 519 } 520 Visit(EnumType enumType)521 protected override void Visit(EnumType enumType) 522 { 523 int index; 524 if (!this.AddObjectToSeenListAndHashBuilder(enumType, out index)) 525 { 526 return; 527 } 528 529 this.AddObjectStartDumpToHashBuilder(enumType, index); 530 531 this.AddObjectContentToHashBuilder(enumType.Identity); 532 this.Visit(enumType.UnderlyingType); 533 534 base.Visit(enumType); 535 536 this.AddObjectEndDumpToHashBuilder(); 537 } 538 Visit(EnumMember enumMember)539 protected override void Visit(EnumMember enumMember) 540 { 541 int index; 542 if (!this.AddObjectToSeenListAndHashBuilder(enumMember, out index)) 543 { 544 return; 545 } 546 547 this.AddObjectStartDumpToHashBuilder(enumMember, index); 548 549 this.AddObjectContentToHashBuilder(enumMember.Name); 550 this.AddObjectContentToHashBuilder(enumMember.Value); 551 552 base.Visit(enumMember); 553 554 this.AddObjectEndDumpToHashBuilder(); 555 } 556 Visit(CollectionType collectionType)557 protected override void Visit(CollectionType collectionType) 558 { 559 int index; 560 if (!this.AddObjectToSeenListAndHashBuilder(collectionType, out index)) 561 { 562 return; 563 } 564 565 this.AddObjectStartDumpToHashBuilder(collectionType, index); 566 567 #region Inner data visit 568 this.AddObjectContentToHashBuilder(collectionType.Identity); 569 // Identity contains Name, NamespaceName and FullName 570 571 base.Visit(collectionType); 572 573 #endregion 574 575 this.AddObjectEndDumpToHashBuilder(); 576 } 577 Visit(RefType refType)578 protected override void Visit(RefType refType) 579 { 580 int index; 581 if (!this.AddObjectToSeenListAndHashBuilder(refType, out index)) 582 { 583 return; 584 } 585 586 this.AddObjectStartDumpToHashBuilder(refType, index); 587 588 #region Inner data visit 589 this.AddObjectContentToHashBuilder(refType.Identity); 590 // Identity contains Name, NamespaceName and FullName 591 592 base.Visit(refType); 593 594 #endregion 595 596 this.AddObjectEndDumpToHashBuilder(); 597 } 598 Visit(EntityTypeBase entityTypeBase)599 protected override void Visit(EntityTypeBase entityTypeBase) 600 { 601 base.Visit(entityTypeBase); 602 } 603 Visit(Facet facet)604 protected override void Visit(Facet facet) 605 { 606 int index; 607 if (facet.Name != DbProviderManifest.NullableFacetName) 608 { 609 // skip all the non interesting facets 610 return; 611 } 612 613 if (!this.AddObjectToSeenListAndHashBuilder(facet, out index)) 614 { 615 return; 616 } 617 618 this.AddObjectStartDumpToHashBuilder(facet, index); 619 620 #region Inner data visit 621 this.AddObjectContentToHashBuilder(facet.Identity); 622 // Identity already contains Name 623 this.AddObjectContentToHashBuilder(facet.Value); 624 625 base.Visit(facet); 626 627 #endregion 628 629 this.AddObjectEndDumpToHashBuilder(); 630 } 631 Visit(EdmFunction edmFunction)632 protected override void Visit(EdmFunction edmFunction) 633 { 634 // View Generation doesn't deal with functions 635 // so just return; 636 } 637 Visit(ComplexType complexType)638 protected override void Visit(ComplexType complexType) 639 { 640 int index; 641 if (!this.AddObjectToSeenListAndHashBuilder(complexType, out index)) 642 { 643 return; 644 } 645 646 this.AddObjectStartDumpToHashBuilder(complexType, index); 647 648 #region Inner data visit 649 this.AddObjectContentToHashBuilder(complexType.Abstract); 650 this.AddObjectContentToHashBuilder(complexType.Identity); 651 // Identity covers, FullName, Name, and NamespaceName 652 653 base.Visit(complexType); 654 655 #endregion 656 657 this.AddObjectEndDumpToHashBuilder(); 658 } 659 Visit(PrimitiveType primitiveType)660 protected override void Visit(PrimitiveType primitiveType) 661 { 662 int index; 663 if (!this.AddObjectToSeenListAndHashBuilder(primitiveType, out index)) 664 { 665 return; 666 } 667 668 this.AddObjectStartDumpToHashBuilder(primitiveType, index); 669 670 #region Inner data visit 671 this.AddObjectContentToHashBuilder(primitiveType.Name); 672 this.AddObjectContentToHashBuilder(primitiveType.NamespaceName); 673 674 base.Visit(primitiveType); 675 676 #endregion 677 678 this.AddObjectEndDumpToHashBuilder(); 679 } 680 Visit(FunctionParameter functionParameter)681 protected override void Visit(FunctionParameter functionParameter) 682 { 683 int index; 684 if (!this.AddObjectToSeenListAndHashBuilder(functionParameter, out index)) 685 { 686 return; 687 } 688 689 this.AddObjectStartDumpToHashBuilder(functionParameter, index); 690 691 #region Inner data visit 692 this.AddObjectContentToHashBuilder(functionParameter.Identity); 693 // Identity already has Name 694 this.AddObjectContentToHashBuilder(functionParameter.Mode); 695 696 base.Visit(functionParameter); 697 698 #endregion 699 700 this.AddObjectEndDumpToHashBuilder(); 701 } 702 Visit(DbProviderManifest providerManifest)703 protected override void Visit(DbProviderManifest providerManifest) 704 { 705 // the provider manifest will be checked by all the other types lining up. 706 // no need to store more info. 707 } 708 #endregion 709 710 #region hasher helper method 711 712 internal string HashValue 713 { 714 get 715 { 716 return m_hashSourceBuilder.ComputeHash(); 717 } 718 } 719 Clean()720 private void Clean() 721 { 722 this.m_hashSourceBuilder = new CompressingHashBuilder(MetadataHelper.CreateMetadataHashAlgorithm(m_MappingVersion)); 723 this.m_instanceNumber = 0; 724 this.m_itemsAlreadySeen = new Dictionary<object, int>(); 725 } 726 727 /// <summary> 728 /// if already seen, then out the object instance index, return false; 729 /// if haven't seen, then add it to the m_itemAlreadySeen, out the current index, return true 730 /// </summary> 731 /// <param name="o"></param> 732 /// <param name="indexSeen"></param> 733 /// <returns></returns> TryAddSeenItem(Object o, out int indexSeen)734 private bool TryAddSeenItem(Object o, out int indexSeen) 735 { 736 if (!this.m_itemsAlreadySeen.TryGetValue(o, out indexSeen)) 737 { 738 this.m_itemsAlreadySeen.Add(o, this.m_instanceNumber); 739 740 indexSeen = this.m_instanceNumber; 741 this.m_instanceNumber++; 742 743 return true; 744 } 745 return false; 746 } 747 748 /// <summary> 749 /// if the object has seen, then add the seen object style to the hash source, return false; 750 /// if not, then add it to the seen list, and append the object start dump to the hash source, return true 751 /// </summary> 752 /// <param name="o"></param> 753 /// <returns></returns> AddObjectToSeenListAndHashBuilder(object o, out int instanceIndex)754 private bool AddObjectToSeenListAndHashBuilder(object o, out int instanceIndex) 755 { 756 if (o == null) 757 { 758 instanceIndex = -1; 759 return false; 760 } 761 if (!TryAddSeenItem(o, out instanceIndex)) 762 { 763 this.AddObjectStartDumpToHashBuilder(o, instanceIndex); 764 this.AddSeenObjectToHashBuilder(o, instanceIndex); 765 this.AddObjectEndDumpToHashBuilder(); 766 return false; 767 } 768 return true; 769 } 770 AddSeenObjectToHashBuilder(object o, int instanceIndex)771 private void AddSeenObjectToHashBuilder(object o, int instanceIndex) 772 { 773 Debug.Assert(instanceIndex >= 0, "referencing index should not be less than 0"); 774 this.m_hashSourceBuilder.AppendLine("Instance Reference: " + instanceIndex); 775 } 776 AddObjectStartDumpToHashBuilder(object o, int objectIndex)777 private void AddObjectStartDumpToHashBuilder(object o, int objectIndex) 778 { 779 this.m_hashSourceBuilder.AppendObjectStartDump(o, objectIndex); 780 } 781 AddObjectEndDumpToHashBuilder()782 private void AddObjectEndDumpToHashBuilder() 783 { 784 this.m_hashSourceBuilder.AppendObjectEndDump(); 785 } 786 AddObjectContentToHashBuilder(object content)787 private void AddObjectContentToHashBuilder(object content) 788 { 789 if (content != null) 790 { 791 IFormattable formatContent = content as IFormattable; 792 if (formatContent != null) 793 { 794 // if the content is formattable, the following code made it culture invariant, 795 // for instance, the int, "30,000" can be formatted to "30-000" if the user 796 // has a different language and region setting 797 this.m_hashSourceBuilder.AppendLine(formatContent.ToString(null, CultureInfo.InvariantCulture)); 798 } 799 else 800 { 801 this.m_hashSourceBuilder.AppendLine(content.ToString()); 802 } 803 } 804 else 805 { 806 this.m_hashSourceBuilder.AppendLine("NULL"); 807 } 808 } 809 810 /// <summary> 811 /// Add V2 schema properties and attributes to the hash builder 812 /// </summary> 813 /// <param name="content"></param> 814 /// <param name="defaultValue"></param> AddV2ObjectContentToHashBuilder(object content, double version)815 private void AddV2ObjectContentToHashBuilder(object content, double version) 816 { 817 // if the version number is greater than or equal to V2, then we add the value 818 if (version >= XmlConstants.EdmVersionForV2) 819 { 820 this.AddObjectContentToHashBuilder(content); 821 } 822 } 823 GetMappingClosureHash(double mappingVersion, StorageEntityContainerMapping storageEntityContainerMapping)824 internal static string GetMappingClosureHash(double mappingVersion, StorageEntityContainerMapping storageEntityContainerMapping) 825 { 826 Debug.Assert(storageEntityContainerMapping != null, "storageEntityContainerMapping is null!"); 827 828 MetadataMappingHasherVisitor visitor = new MetadataMappingHasherVisitor(mappingVersion); 829 visitor.Visit(storageEntityContainerMapping); 830 return visitor.HashValue; 831 } 832 #endregion 833 834 } 835 } 836