Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Objects / ObjectParameter.cs
1 //---------------------------------------------------------------------
2 // <copyright file="ObjectParameter.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner [....]
7 // @backupowner [....]
8 //---------------------------------------------------------------------
9
10 namespace System.Data.Objects
11 {
12     using System;
13     using System.Data;
14     using System.Data.Common.CommandTrees;
15     using System.Data.Metadata.Edm;
16     using System.Diagnostics;
17
18     /// <summary> 
19     ///   This class represents a query parameter at the object layer, which consists
20     ///   of a Name, a Type and a Value.
21     /// </summary>
22     public sealed class ObjectParameter
23     {
24         #region Static Methods
25
26         // --------------
27         // Static Methods
28         // --------------
29
30         #region ValidateParameterName
31
32         /// <summary>
33         ///   This internal method uses regular expression matching to ensure that the
34         ///   specified parameter name is valid. Parameter names must start with a letter,
35         ///   and may only contain letters (A-Z, a-z), numbers (0-9) and underscores (_).
36         /// </summary>
37         internal static bool ValidateParameterName (string name)
38         {
39             // Note: Parameter names must begin with a letter, and may contain only
40             // letters, numbers and underscores.
41             return DbCommandTree.IsValidParameterName(name);
42         }
43
44         #endregion
45
46         #endregion
47
48         #region Public Constructors
49
50         // -------------------
51         // Public Constructors
52         // -------------------
53
54         #region ObjectParameter (string, Type)
55
56         /// <summary>
57         ///   This constructor creates an unbound (i.e., value-less) parameter from the
58         ///   specified name and type. The value can be set at any time through the 
59         ///   public 'Value' property.
60         /// </summary>
61         /// <param name="name">
62         ///   The parameter name.
63         /// </param>
64         /// <param name="type">
65         ///   The CLR type of the parameter.
66         /// </param>
67         /// <returns>
68         ///   A new unbound ObjectParameter instance.
69         /// </returns>
70         /// <exception cref="ArgumentNullException">
71         ///   If the value of either argument is null.
72         /// </exception>
73         /// <exception cref="ArgumentOutOfRangeException">
74         ///   If the value of the name argument is invalid. Parameter names must start
75         ///   with a letter and may only contain letters (A-Z, a-z), numbers (0-9) and 
76         ///   underscores (_).
77         /// </exception>
78         public ObjectParameter (string name, Type type)
79         {
80             EntityUtil.CheckArgumentNull(name, "name");
81             EntityUtil.CheckArgumentNull(type, "type");
82
83             if (!ObjectParameter.ValidateParameterName(name))
84             {
85                 throw EntityUtil.Argument(System.Data.Entity.Strings.ObjectParameter_InvalidParameterName(name), "name");
86             }
87
88             this._name  = name;
89             this._type  = type;
90
91             // If the parameter type is Nullable<>, we need to extract out the underlying
92             // Nullable<> type argument.
93             this._mappableType = System.Data.Objects.ELinq.TypeSystem.GetNonNullableType(this._type);
94         }
95
96         #endregion
97
98         #region ObjectParameter (string, object)
99
100         /// <summary>
101         ///   This constructor creates a fully-bound (i.e., valued) parameter from the
102         ///   specified name and value. The type is inferred from the initial value, but
103         ///   the value can be changed at any time through the public 'Value' property.
104         /// </summary>
105         /// <param name="name">
106         ///   The parameter name.
107         /// </param>
108         /// <param name="value">
109         ///   The initial value (and inherently, type) of the parameter.
110         /// </param>
111         /// <returns>
112         ///   A new fully-bound ObjectParameter instance.
113         /// </returns>
114         /// <exception cref="ArgumentNullException">
115         ///   If the value of either argument is null.
116         /// </exception>
117         /// <exception cref="ArgumentOutOfRangeException">
118         ///   If the value of the name argument is invalid. Parameter names must start
119         ///   with a letter and may only contain letters (A-Z, a-z), numbers (0-9) and 
120         ///   underscores (_).
121         /// </exception>
122         public ObjectParameter (string name, object value)
123         {
124             EntityUtil.CheckArgumentNull(name, "name");
125             EntityUtil.CheckArgumentNull(value, "value");
126
127             if (!ObjectParameter.ValidateParameterName(name))
128             {
129                 throw EntityUtil.Argument(System.Data.Entity.Strings.ObjectParameter_InvalidParameterName(name), "name");
130             }
131
132             this._name  = name;
133             this._type  = value.GetType();
134             this._value = value;
135
136             // If the parameter type is Nullable<>, we need to extract out the underlying
137             // Nullable<> type argument.
138             this._mappableType = System.Data.Objects.ELinq.TypeSystem.GetNonNullableType(this._type);
139         }
140
141         #endregion
142
143         #endregion
144
145         #region Private Constructors
146
147         // -------------------
148         // Copy Constructor
149         // -------------------
150
151         /// <summary>
152         ///   This constructor is used by <see cref="ShallowCopy"/> to create a new ObjectParameter
153         ///   with field values taken from the field values of an existing ObjectParameter.
154         /// </summary>
155         /// <param name="template">
156         ///   The existing ObjectParameter instance from which field values should be taken.
157         /// </param>
158         /// <returns>
159         ///   A new ObjectParameter instance with the same field values as the specified ObjectParameter
160         /// </returns>
161         private ObjectParameter(ObjectParameter template)
162         {
163             Debug.Assert(template != null, "Template ObjectParameter cannot be null");
164
165             this._name = template._name;
166             this._type = template._type;
167             this._mappableType = template._mappableType;
168             this._effectiveType = template._effectiveType;
169             this._value = template._value;
170         }
171                 
172         #endregion
173
174         #region Private Fields
175
176         // --------------
177         // Private Fields
178         // --------------
179
180         /// <summary>
181         ///   The name of the parameter. Cannot be null and is immutable.
182         /// </summary>
183         private string _name;
184
185         /// <summary>
186         ///   The CLR type of the parameter. Cannot be null and is immutable.
187         /// </summary>
188         private Type _type;
189
190         /// <summary>
191         ///   The mappable CLR type of the parameter. Unless the parameter type is
192         ///   Nullable, this type is equal to the parameter type. In the case of
193         ///   Nullable parameters, this type is the underlying Nullable argument
194         ///   type. Cannot be null and is immutable.
195         /// </summary>
196         private Type _mappableType;
197
198         /// <summary>
199         ///     Used to specify the exact metadata type of this parameter.
200         ///     Typically null, can only be set using the internal <see cref="TypeUsage"/> property.
201         /// </summary>
202         private TypeUsage _effectiveType;
203
204         /// <summary>
205         ///   The value of the parameter. Does not need to be bound until execution
206         ///   time and can be modified at any time.
207         /// </summary>
208         private object _value;
209
210         #endregion
211
212         #region Public Properties
213
214         // -----------------
215         // Public Properties
216         // -----------------
217
218         /// <summary>
219         ///   The parameter name, which can only be set through a constructor.
220         /// </summary>
221         public string Name
222         {
223             get
224             {
225                 return this._name;
226             }
227         }
228
229         /// <summary>
230         ///   The parameter type, which can only be set through a constructor.
231         /// </summary>
232         public Type ParameterType
233         {
234             get
235             {
236                 return this._type;
237             }
238         }
239
240         /// <summary>
241         ///   The parameter value, which can be set at any time (and subsequently 
242         ///   changed) before query execution. Note that type-checking is not 
243         ///   enforced between the declared parameter type and the type of the 
244         ///   specified value; such validation is left up to the underlying 
245         ///   provider(s) at execution time.
246         /// </summary>
247         public object Value
248         {
249             get
250             {
251                 return this._value;
252             }
253
254             set
255             {
256                 this._value = value;
257             }
258         }
259
260         #endregion
261
262         #region Internal Properties
263
264         // -------------------
265         // Internal Properties
266         // -------------------
267
268         /// <summary>
269         ///     Gets or sets a <see cref="TypeUsage"/> that specifies the exact
270         ///     type of which the parameter value is considered an instance.
271         /// </summary>
272         internal TypeUsage TypeUsage
273         {
274             get
275             {
276                 return _effectiveType;
277             }
278
279             set
280             {
281                 Debug.Assert(null == _effectiveType, "Effective type should only be set once");
282                 _effectiveType = value;
283             }
284         }
285
286         /// <summary>
287         ///   The mappable parameter type; this is primarily used to handle the case of 
288         ///   Nullable parameter types. For example, metadata knows nothing about 'int?', 
289         ///   only 'Int32'. For internal use only.
290         /// </summary>
291         internal Type MappableType
292         {
293             get
294             {
295                 return this._mappableType;
296             }
297         }
298         
299         #endregion
300
301         #region Internal Methods
302
303         // ----------------
304         // Internal Methods
305         // ----------------
306
307         /// <summary>
308         /// Creates a new ObjectParameter instance with identical field values to this instance.
309         /// </summary>
310         /// <returns>The new ObjectParameter instance</returns>
311         internal ObjectParameter ShallowCopy()
312         {
313             return new ObjectParameter(this);
314         }
315                 
316         /// <summary>
317         ///   This internal method ensures that the specified type is a scalar
318         ///   type supported by the underlying provider by ensuring that scalar 
319         ///   metadata for this type is retrievable.
320         /// </summary>
321         internal bool ValidateParameterType (ClrPerspective perspective)
322         {
323             TypeUsage type = null;
324
325             // The parameter type metadata is only valid if it's scalar or enumeration type metadata.
326             if ((perspective.TryGetType(this._mappableType, out type)) && 
327                 (TypeSemantics.IsScalarType(type)))
328             {
329                 return true;
330             }
331
332             return false;
333         }
334
335         #endregion
336     }
337 }