1 //--------------------------------------------------------------------- 2 // <copyright file="EntitySet.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.Text; 13 using System.Diagnostics; 14 using System.Threading; 15 using System.Data.Common.Utils; 16 using System.Collections.ObjectModel; 17 18 namespace System.Data.Metadata.Edm 19 { 20 /// <summary> 21 /// concrete Class for representing a entity set 22 /// </summary> 23 public class EntitySet : EntitySetBase 24 { 25 #region Constructors 26 /// <summary> 27 /// The constructor for constructing the EntitySet with a given name and an entity type 28 /// </summary> 29 /// <param name="name">The name of the EntitySet</param> 30 /// <param name="schema">The db schema</param> 31 /// <param name="table">The db table</param> 32 /// <param name="definingQuery">The provider specific query that should be used to retrieve the EntitySet</param> 33 /// <param name="entityType">The entity type of the entities that this entity set type contains</param> 34 /// <exception cref="System.ArgumentNullException">Thrown if the argument name or entityType is null</exception> EntitySet(string name, string schema, string table, string definingQuery, EntityType entityType)35 internal EntitySet(string name, string schema, string table, string definingQuery, EntityType entityType) 36 : base(name, schema, table, definingQuery, entityType) 37 { 38 } 39 #endregion 40 41 #region Fields 42 private ReadOnlyCollection<Tuple<AssociationSet, ReferentialConstraint>> _foreignKeyDependents; 43 private ReadOnlyCollection<Tuple<AssociationSet, ReferentialConstraint>> _foreignKeyPrincipals; 44 private volatile bool _hasForeignKeyRelationships; 45 private volatile bool _hasIndependentRelationships; 46 #endregion 47 48 #region Properties 49 /// <summary> 50 /// Returns the kind of the type 51 /// </summary> 52 public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.EntitySet; } } 53 54 /// <summary> 55 /// Gets/Sets the entity type of this entity set 56 /// </summary> 57 public new EntityType ElementType 58 { 59 get 60 { 61 return (EntityType)base.ElementType; 62 } 63 } 64 65 /// <summary> 66 /// Returns the associations and constraints where "this" EntitySet particpates as the Principal end. 67 /// From the results of this list, you can retrieve the Dependent IRelatedEnds 68 /// </summary> 69 internal ReadOnlyCollection<Tuple<AssociationSet, ReferentialConstraint>> ForeignKeyDependents 70 { 71 get 72 { 73 if (_foreignKeyDependents == null) 74 { 75 InitializeForeignKeyLists(); 76 } 77 return _foreignKeyDependents; 78 } 79 } 80 81 /// <summary> 82 /// Returns the associations and constraints where "this" EntitySet particpates as the Dependent end. 83 /// From the results of this list, you can retrieve the Principal IRelatedEnds 84 /// </summary> 85 internal ReadOnlyCollection<Tuple<AssociationSet, ReferentialConstraint>> ForeignKeyPrincipals 86 { 87 get 88 { 89 if (_foreignKeyPrincipals == null) 90 { 91 InitializeForeignKeyLists(); 92 } 93 return _foreignKeyPrincipals; 94 } 95 } 96 97 /// <summary> 98 /// True if this entity set participates in any foreign key relationships, otherwise false. 99 /// </summary> 100 internal bool HasForeignKeyRelationships 101 { 102 get 103 { 104 if (_foreignKeyPrincipals == null) 105 { 106 InitializeForeignKeyLists(); 107 } 108 return _hasForeignKeyRelationships; 109 } 110 } 111 112 /// <summary> 113 /// True if this entity set participates in any independent relationships, otherwise false. 114 /// </summary> 115 internal bool HasIndependentRelationships 116 { 117 get 118 { 119 if (_foreignKeyPrincipals == null) 120 { 121 InitializeForeignKeyLists(); 122 } 123 return _hasIndependentRelationships; 124 } 125 } 126 127 #endregion 128 129 #region Methods InitializeForeignKeyLists()130 private void InitializeForeignKeyLists() 131 { 132 var dependents = new List<Tuple<AssociationSet, ReferentialConstraint>>(); 133 var principals = new List<Tuple<AssociationSet, ReferentialConstraint>>(); 134 bool foundFkRelationship = false; 135 bool foundIndependentRelationship = false; 136 foreach (AssociationSet associationSet in MetadataHelper.GetAssociationsForEntitySet(this)) 137 { 138 if (associationSet.ElementType.IsForeignKey) 139 { 140 foundFkRelationship = true; 141 Debug.Assert(associationSet.ElementType.ReferentialConstraints.Count == 1, "Expected exactly one constraint for FK"); 142 ReferentialConstraint constraint = associationSet.ElementType.ReferentialConstraints[0]; 143 if (constraint.ToRole.GetEntityType().IsAssignableFrom(this.ElementType) || 144 this.ElementType.IsAssignableFrom(constraint.ToRole.GetEntityType())) 145 { 146 // Dependents 147 dependents.Add(new Tuple<AssociationSet, ReferentialConstraint>(associationSet, constraint)); 148 } 149 if (constraint.FromRole.GetEntityType().IsAssignableFrom(this.ElementType) || 150 this.ElementType.IsAssignableFrom(constraint.FromRole.GetEntityType())) 151 { 152 // Principals 153 principals.Add(new Tuple<AssociationSet, ReferentialConstraint>(associationSet, constraint)); 154 } 155 } 156 else 157 { 158 foundIndependentRelationship = true; 159 } 160 } 161 162 _hasForeignKeyRelationships = foundFkRelationship; 163 _hasIndependentRelationships = foundIndependentRelationship; 164 165 var readOnlyDependents = dependents.AsReadOnly(); 166 var readOnlyPrincipals = principals.AsReadOnly(); 167 168 Interlocked.CompareExchange(ref _foreignKeyDependents, readOnlyDependents, null); 169 Interlocked.CompareExchange(ref _foreignKeyPrincipals, readOnlyPrincipals, null); 170 } 171 #endregion 172 } 173 } 174