Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / Edm / EntitySet.cs
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>
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
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 }