File: NavigationProperty.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (168 lines) | stat: -rw-r--r-- 6,972 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//---------------------------------------------------------------------
// <copyright file="NavigationProperty.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.Threading;
using System.Linq;

namespace System.Data.Metadata.Edm
{
    /// <summary>
    /// Represent the edm navigation property class
    /// </summary>
    public sealed class NavigationProperty : EdmMember
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the navigation property class
        /// </summary>
        /// <param name="name">name of the navigation property</param>
        /// <param name="typeUsage">TypeUsage object containing the navigation property type and its facets</param>
        /// <exception cref="System.ArgumentNullException">Thrown if name or typeUsage arguments are null</exception>
        /// <exception cref="System.ArgumentException">Thrown if name argument is empty string</exception>
        internal NavigationProperty(string name, TypeUsage typeUsage)
            : base(name, typeUsage)
        {
            EntityUtil.CheckStringArgument(name, "name");
            EntityUtil.GenericCheckArgumentNull(typeUsage, "typeUsage");
            _accessor = new NavigationPropertyAccessor(name);
        }

        /// <summary>
        /// Initializes a new OSpace instance of the property class
        /// </summary>
        /// <param name="name">name of the property</param>
        /// <param name="typeUsage">TypeUsage object containing the property type and its facets</param>
        /// <param name="propertyInfo">for the property</param>
        internal NavigationProperty(string name, TypeUsage typeUsage, System.Reflection.PropertyInfo propertyInfo)
            : this(name, typeUsage)
        {
            System.Diagnostics.Debug.Assert(name == propertyInfo.Name, "different PropertyName?");
            if (null != propertyInfo)
            {
                System.Reflection.MethodInfo method;
                
                method = propertyInfo.GetGetMethod();
                PropertyGetterHandle = ((null != method) ? method.MethodHandle : default(System.RuntimeMethodHandle));
            }
        }
        #endregion

        /// <summary>
        /// Returns the kind of the type
        /// </summary>
        public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.NavigationProperty; } }

        #region Fields
        internal const string RelationshipTypeNamePropertyName = "RelationshipType";
        internal const string ToEndMemberNamePropertyName = "ToEndMember";
        private RelationshipType _relationshipType;
        private RelationshipEndMember _toEndMember;
        private RelationshipEndMember _fromEndMember;

        /// <summary>Store the handle, allowing the PropertyInfo/MethodInfo/Type references to be GC'd</summary>
        internal readonly System.RuntimeMethodHandle PropertyGetterHandle;

        /// <summary>cached dynamic methods to access the property values from a CLR instance</summary> 
        private readonly NavigationPropertyAccessor _accessor;
        #endregion

        /// <summary>
        /// Gets/Sets the relationship type that this navigation property operates on
        /// </summary>
        /// <exception cref="System.InvalidOperationException">Thrown if the NavigationProperty instance is in ReadOnly state</exception>
        [MetadataProperty(BuiltInTypeKind.RelationshipType, false)]
        public RelationshipType RelationshipType
        {
            get
            {
                return _relationshipType;
            }
            internal set
            {
                _relationshipType = value;
            }
        }

        /// <summary>
        /// Gets/Sets the to relationship end member in the navigation
        /// </summary>
        /// <exception cref="System.InvalidOperationException">Thrown if the NavigationProperty instance is in ReadOnly state</exception>
        [MetadataProperty(BuiltInTypeKind.RelationshipEndMember, false)]
        public RelationshipEndMember ToEndMember
        {
            get
            {
                return _toEndMember;
            }
            internal set
            {
                _toEndMember = value;
            }
        }

        /// <summary>
        /// Gets/Sets the from relationship end member in the navigation
        /// </summary>
        /// <exception cref="System.InvalidOperationException">Thrown if the NavigationProperty instance is in ReadOnly state</exception>
        [MetadataProperty(BuiltInTypeKind.RelationshipEndMember, false)]
        public RelationshipEndMember FromEndMember
        {
            get
            {
                return _fromEndMember;
            }
            internal set
            {
                _fromEndMember = value;
            }
        }

        internal NavigationPropertyAccessor Accessor
        {
            get { return _accessor; }
        }

        /// <summary>
        /// Where the given navigation property is on the dependent end of a referential constraint,
        /// returns the foreign key properties. Otherwise, returns an empty set. We will return the members in the order
        /// of the principal end key properties.
        /// </summary>
        /// <returns>Foreign key properties</returns>
        public IEnumerable<EdmProperty> GetDependentProperties()
        {
            // Get the declared type
            AssociationType associationType = (AssociationType)this.RelationshipType;
            Debug.Assert(
                         associationType.ReferentialConstraints != null,
                         "ReferenceConstraints cannot be null");

            if (associationType.ReferentialConstraints.Count > 0)
            {
                ReferentialConstraint rc = associationType.ReferentialConstraints[0];
                RelationshipEndMember dependentEndMember = rc.ToRole;

                if (dependentEndMember.EdmEquals(this.FromEndMember))
                {
                    //Order the dependant properties in the order of principal end's key members.
                    var keyMembers = rc.FromRole.GetEntityType().KeyMembers;
                    var dependantProperties = new List<EdmProperty>(keyMembers.Count);
                    for (int i = 0; i < keyMembers.Count; i++)
                    {
                        dependantProperties.Add(rc.ToProperties[rc.FromProperties.IndexOf(((EdmProperty)keyMembers[i]))]);
                    }
                    return dependantProperties.AsReadOnly();
                }
            }
            
            return Enumerable.Empty<EdmProperty>();
        }
    }
}