1 //---------------------------------------------------------------------
2 // <copyright file="Relationship.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 namespace System.Data.EntityModel.SchemaObjectModel
12 using System.Collections.Generic;
13 using System.Data.Metadata.Edm;
14 using System.Data.Objects.DataClasses;
15 using System.Diagnostics;
19 /// Represents an Association element
21 internal sealed class Relationship : SchemaType, IRelationship
23 private RelationshipKind _relationshipKind;
24 private RelationshipEndCollection _ends;
25 private List<ReferentialConstraint> _constraints;
26 private bool _isForeignKey;
29 /// Construct a Relationship object
31 /// <param name="parent">the parent</param>
32 /// <param name="kind">the kind of relationship</param>
33 public Relationship(Schema parent, RelationshipKind kind)
36 RelationshipKind = kind;
38 if (Schema.DataModel == SchemaDataModelOption.EntityDataModel)
40 _isForeignKey = false;
41 OtherContent.Add(Schema.SchemaSource);
43 else if (Schema.DataModel == SchemaDataModelOption.ProviderDataModel)
51 /// List of Ends defined for this Association
53 public IList<IRelationshipEnd> Ends
58 _ends = new RelationshipEndCollection();
64 /// Returns the list of constraints on this relation
66 public IList<ReferentialConstraint> Constraints
70 if (_constraints == null)
72 _constraints = new List<ReferentialConstraint>();
78 public bool TryGetEnd( string roleName, out IRelationshipEnd end )
80 return _ends.TryGetEnd( roleName, out end );
85 /// Is this an Association
87 public RelationshipKind RelationshipKind
91 return _relationshipKind;
95 _relationshipKind = value;
100 /// Is this a foreign key (aka foreign key) relationship?
102 public bool IsForeignKey
104 get { return _isForeignKey; }
108 /// do whole element validation
110 /// <returns></returns>
111 internal override void Validate()
115 bool foundOperations = false;
116 foreach ( RelationshipEnd end in Ends )
119 if ( RelationshipKind == RelationshipKind.Association )
121 if ( end.Operations.Count > 0 )
123 if ( foundOperations )
124 end.AddError( ErrorCode.InvalidOperation, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.InvalidOperationMultipleEndsInAssociation);
125 foundOperations = true;
130 if (Constraints.Count == 0)
132 if (this.Schema.DataModel == SchemaDataModelOption.ProviderDataModel)
134 AddError(ErrorCode.MissingConstraintOnRelationshipType,
135 EdmSchemaErrorSeverity.Error,
136 System.Data.Entity.Strings.MissingConstraintOnRelationshipType(FQName));
141 foreach (ReferentialConstraint constraint in Constraints)
143 constraint.Validate();
149 /// do whole element resolution
151 internal override void ResolveTopLevelNames()
153 base.ResolveTopLevelNames();
155 foreach ( RelationshipEnd end in Ends )
156 end.ResolveTopLevelNames();
158 foreach (ReferentialConstraint referentialConstraint in Constraints)
160 referentialConstraint.ResolveTopLevelNames();
164 protected override bool HandleElement(XmlReader reader)
166 if (base.HandleElement(reader))
170 else if (CanHandleElement(reader, XmlConstants.End))
172 HandleEndElement(reader);
175 else if (CanHandleElement(reader, XmlConstants.ReferentialConstraint))
177 HandleConstraintElement(reader);
184 /// handle the End child element
186 /// <param name="reader">XmlReader positioned at the end element</param>
187 private void HandleEndElement(XmlReader reader)
189 Debug.Assert(reader != null);
190 RelationshipEnd end = new RelationshipEnd(this);
195 AddError( ErrorCode.InvalidAssociation, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.TooManyAssociationEnds(FQName ) );
203 /// handle the constraint element
205 /// <param name="reader">XmlReader positioned at the constraint element</param>
206 private void HandleConstraintElement(XmlReader reader)
208 Debug.Assert(reader != null);
210 ReferentialConstraint constraint = new ReferentialConstraint(this);
211 constraint.Parse(reader);
212 this.Constraints.Add(constraint);
214 if (this.Schema.DataModel == SchemaDataModelOption.EntityDataModel && this.Schema.SchemaVersion >= XmlConstants.EdmVersionForV2)
216 // in V2, referential constraint implies foreign key
217 _isForeignKey = true;