1 //---------------------------------------------------------------------
2 // <copyright file="NavigationProperty.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9 using System
.Collections
.Generic
;
10 using System
.Data
.Common
;
11 using System
.Diagnostics
;
12 using System
.Threading
;
15 namespace System
.Data
.Metadata
.Edm
18 /// Represent the edm navigation property class
20 public sealed class NavigationProperty
: EdmMember
24 /// Initializes a new instance of the navigation property class
26 /// <param name="name">name of the navigation property</param>
27 /// <param name="typeUsage">TypeUsage object containing the navigation property type and its facets</param>
28 /// <exception cref="System.ArgumentNullException">Thrown if name or typeUsage arguments are null</exception>
29 /// <exception cref="System.ArgumentException">Thrown if name argument is empty string</exception>
30 internal NavigationProperty(string name
, TypeUsage typeUsage
)
31 : base(name
, typeUsage
)
33 EntityUtil
.CheckStringArgument(name
, "name");
34 EntityUtil
.GenericCheckArgumentNull(typeUsage
, "typeUsage");
35 _accessor
= new NavigationPropertyAccessor(name
);
39 /// Initializes a new OSpace instance of the property class
41 /// <param name="name">name of the property</param>
42 /// <param name="typeUsage">TypeUsage object containing the property type and its facets</param>
43 /// <param name="propertyInfo">for the property</param>
44 internal NavigationProperty(string name
, TypeUsage typeUsage
, System
.Reflection
.PropertyInfo propertyInfo
)
45 : this(name
, typeUsage
)
47 System
.Diagnostics
.Debug
.Assert(name
== propertyInfo
.Name
, "different PropertyName?");
48 if (null != propertyInfo
)
50 System
.Reflection
.MethodInfo method
;
52 method
= propertyInfo
.GetGetMethod();
53 PropertyGetterHandle
= ((null != method
) ? method
.MethodHandle
: default(System
.RuntimeMethodHandle
));
59 /// Returns the kind of the type
61 public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.NavigationProperty; }
}
64 internal const string RelationshipTypeNamePropertyName
= "RelationshipType";
65 internal const string ToEndMemberNamePropertyName
= "ToEndMember";
66 private RelationshipType _relationshipType
;
67 private RelationshipEndMember _toEndMember
;
68 private RelationshipEndMember _fromEndMember
;
70 /// <summary>Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd</summary>
71 internal readonly System
.RuntimeMethodHandle PropertyGetterHandle
;
73 /// <summary>cached dynamic methods to access the property values from a CLR instance</summary>
74 private readonly NavigationPropertyAccessor _accessor
;
78 /// Gets/Sets the relationship type that this navigation property operates on
80 /// <exception cref="System.InvalidOperationException">Thrown if the NavigationProperty instance is in ReadOnly state</exception>
81 [MetadataProperty(BuiltInTypeKind
.RelationshipType
, false)]
82 public RelationshipType RelationshipType
86 return _relationshipType
;
90 _relationshipType
= value;
95 /// Gets/Sets the to relationship end member in the navigation
97 /// <exception cref="System.InvalidOperationException">Thrown if the NavigationProperty instance is in ReadOnly state</exception>
98 [MetadataProperty(BuiltInTypeKind
.RelationshipEndMember
, false)]
99 public RelationshipEndMember ToEndMember
107 _toEndMember
= value;
112 /// Gets/Sets the from relationship end member in the navigation
114 /// <exception cref="System.InvalidOperationException">Thrown if the NavigationProperty instance is in ReadOnly state</exception>
115 [MetadataProperty(BuiltInTypeKind
.RelationshipEndMember
, false)]
116 public RelationshipEndMember FromEndMember
120 return _fromEndMember
;
124 _fromEndMember
= value;
128 internal NavigationPropertyAccessor Accessor
130 get { return _accessor; }
134 /// Where the given navigation property is on the dependent end of a referential constraint,
135 /// returns the foreign key properties. Otherwise, returns an empty set. We will return the members in the order
136 /// of the principal end key properties.
138 /// <returns>Foreign key properties</returns>
139 public IEnumerable
<EdmProperty
> GetDependentProperties()
141 // Get the declared type
142 AssociationType associationType
= (AssociationType
)this.RelationshipType
;
144 associationType
.ReferentialConstraints
!= null,
145 "ReferenceConstraints cannot be null");
147 if (associationType
.ReferentialConstraints
.Count
> 0)
149 ReferentialConstraint rc
= associationType
.ReferentialConstraints
[0];
150 RelationshipEndMember dependentEndMember
= rc
.ToRole
;
152 if (dependentEndMember
.EdmEquals(this.FromEndMember
))
154 //Order the dependant properties in the order of principal end's key members.
155 var keyMembers
= rc
.FromRole
.GetEntityType().KeyMembers
;
156 var dependantProperties
= new List
<EdmProperty
>(keyMembers
.Count
);
157 for (int i
= 0; i
< keyMembers
.Count
; i
++)
159 dependantProperties
.Add(rc
.ToProperties
[rc
.FromProperties
.IndexOf(((EdmProperty
)keyMembers
[i
]))]);
161 return dependantProperties
.AsReadOnly();
165 return Enumerable
.Empty
<EdmProperty
>();