acda94e3dc9e9389013540d1c40631ec66549b9d
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Objects / DataClasses / StructuralObject.cs
1 //---------------------------------------------------------------------
2 // <copyright file="DataObject.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9 using System.Data;
10 using System.Diagnostics;
11 using System.Globalization;
12 using System.Reflection;
13 using System.ComponentModel;
14 using System.Runtime.Serialization;
15 using System.Data.Common.Utils;
16
17 namespace System.Data.Objects.DataClasses
18 {
19     /// <summary>
20     /// This class contains the common methods need for an date object.
21     /// </summary>
22     [DataContract(IsReference = true)]
23     [Serializable]
24     public abstract class StructuralObject : INotifyPropertyChanging, INotifyPropertyChanged
25     {
26         // ------
27         // Fields
28         // ------
29
30         // This class contains no fields that are serialized, but it's important to realize that
31         // adding or removing a serialized field is considered a breaking change.  This includes
32         // changing the field type or field name of existing serialized fields. If you need to make
33         // this kind of change, it may be possible, but it will require some custom
34         // serialization/deserialization code.
35
36         /// <summary>
37         /// Public constant name used for change tracking
38         /// Providing this definition allows users to use this constant instead of
39         /// hard-coding the string. This helps to ensure the property name is correct
40         /// and allows faster comparisons in places where we are looking for this specific string.
41         /// Users can still use the case-sensitive string directly instead of the constant,
42         /// it will just be slightly slower on comparison.
43         /// Including the dash (-) character around the name ensures that this will not conflict with
44         /// a real data property, because -EntityKey- is not a valid identifier name
45         /// </summary>
46         public static readonly string EntityKeyPropertyName = "-EntityKey-";
47
48         #region INotifyPropertyChanged Members
49
50         /// <summary>
51         /// Notification that a property has been changed.
52         /// </summary>
53         /// <remarks>
54         /// The PropertyChanged event can indicate all properties on the 
55         /// object have changed by using either a null reference 
56         /// (Nothing in Visual Basic) or String.Empty as the property name 
57         /// in the PropertyChangedEventArgs.
58         /// </remarks>
59         [field: NonSerialized]
60         public event PropertyChangedEventHandler PropertyChanged;
61
62         #endregion
63
64         #region INotifyPropertyChanging Members
65
66         /// <summary>
67         /// Notification that a property is about to be changed.
68         /// </summary>
69         /// <remarks>
70         /// The PropertyChanging event can indicate all properties on the 
71         /// object are changing by using either a null reference 
72         /// (Nothing in Visual Basic) or String.Empty as the property name 
73         /// in the PropertyChangingEventArgs.
74         /// </remarks>
75         [field: NonSerialized]
76         public event PropertyChangingEventHandler PropertyChanging;
77
78         #endregion
79         #region Protected Overrideable
80
81         /// <summary>
82         /// Invokes the PropertyChanged event.  
83         /// </summary>
84         /// <param name="property">
85         /// The string name of the of the changed property.
86         /// </param>
87         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Property")]
88         protected virtual void OnPropertyChanged(string property)
89         {
90             if (PropertyChanged != null)
91             {
92                 PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
93             }
94         }
95
96         /// <summary>
97         /// Invokes the PropertyChanging event.  
98         /// </summary>
99         /// <param name="property">
100         /// The string name of the of the changing property.
101         /// </param>
102         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Property")]
103         protected virtual void OnPropertyChanging(string property)
104         {
105             if (PropertyChanging != null)
106             {
107                 PropertyChanging.Invoke(this, new PropertyChangingEventArgs(property));
108             }
109         }
110
111         #endregion
112         #region Protected Helper
113
114         /// <summary>
115         /// The minimum DateTime value allowed in the store
116         /// </summary>
117         /// <value>
118         /// The minimum DateTime value allowed in the store
119         /// </value>
120         protected static DateTime DefaultDateTimeValue()
121         {
122             return DateTime.Now;
123         }
124
125         /// <summary>
126         /// This method is called whenever a change is going to be made to an object
127         /// property's value.
128         /// </summary>
129         /// <param name="property">
130         /// The name of the changing property.
131         /// </param>
132         /// <param name="value">
133         /// The current value of the property.
134         /// </param> 
135         /// <exception cref="System.ArgumentNullException">
136         /// When parameter member is null (Nothing in Visual Basic).
137         /// </exception>
138         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Property")]
139         protected virtual void ReportPropertyChanging(
140             string property)
141         {
142             EntityUtil.CheckStringArgument(property, "property");
143
144             OnPropertyChanging(property);
145         }
146
147         /// <summary>
148         /// This method is called whenever a change is made to an object 
149         /// property's value.
150         /// </summary>
151         /// <param name="property">
152         /// The name for the changed property.
153         /// </param>        
154         /// <exception cref="System.ArgumentNullException">
155         /// When parameter member is null (Nothing in Visual Basic).
156         /// </exception>
157         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Property")]
158         protected virtual void ReportPropertyChanged(
159             string property)
160         {
161             EntityUtil.CheckStringArgument(property, "property");
162
163             OnPropertyChanged(property);
164         }
165
166         /// <summary>
167         /// Lazily creates a complex type if the current value is null
168         /// </summary>
169         /// <remarks>
170         /// Unlike most of the other helper methods in this class, this one is not static
171         /// because it references the SetValidValue for complex objects, which is also not static
172         /// because it needs a reference to this.
173         /// </remarks>
174         /// <typeparam name="T">
175         /// Type of complex type to get a valid value for
176         /// </typeparam>
177         /// <param name="currentValue">
178         /// The current value of the complex type property
179         /// </param>
180         /// <param name="property">
181         /// The name of the property that is calling this method
182         /// </param>
183         /// <param name="isInitialized">
184         /// True if the field has already been explicitly set by the user.
185         /// </param>
186         /// <returns>
187         /// The new value of the complex type property
188         /// </returns>
189         protected internal T GetValidValue<T>(T currentValue, string property, bool isNullable, bool isInitialized) where T : ComplexObject, new()
190         {
191             // If we support complex type inheritance we will also need to check if T is abstract            
192             if (!isNullable && !isInitialized)
193             {
194                 currentValue = SetValidValue(currentValue, new T(), property);
195             }
196
197             return currentValue;
198         }
199
200         /// <summary>
201         /// This method is called by a ComplexObject contained in this Entity 
202         /// whenever a change is about to be made to a property of the  
203         /// ComplexObject so that the change can be forwarded to the change tracker.
204         /// </summary>
205         /// <param name="entityMemberName">
206         /// The name of the top-level entity property that contains the ComplexObject that is calling this method.
207         /// </param>
208         /// <param name="complexObject">
209         /// The instance of the ComplexObject on which the property is changing.
210         /// </param>
211         /// <param name="complexMemberName">
212         /// The name of the changing property on complexObject.
213         /// </param>                
214         internal abstract void ReportComplexPropertyChanging(
215             string entityMemberName, ComplexObject complexObject, string complexMemberName);
216
217         /// <summary>
218         /// This method is called by a ComplexObject contained in this Entity 
219         /// whenever a change has been made to a property of the  
220         /// ComplexObject so that the change can be forwarded to the change tracker.
221         /// </summary>
222         /// <param name="entityMemberName">
223         /// The name of the top-level entity property that contains the ComplexObject that is calling this method.
224         /// </param>
225         /// <param name="complexObject">
226         /// The instance of the ComplexObject on which the property is changing.
227         /// </param>
228         /// <param name="complexMemberName">
229         /// The name of the changing property on complexObject.
230         /// </param>        
231         internal abstract void ReportComplexPropertyChanged(
232             string entityMemberName, ComplexObject complexObject, string complexMemberName);
233
234         /// <summary>
235         /// Determines whether the structural object is attached to a change tracker or not
236         /// </summary>
237         internal abstract bool IsChangeTracked { get; }
238
239         /// <summary>
240         /// Determines whether the specified byte arrays contain identical values
241         /// </summary>
242         /// <param name="first">The first byte array value to compare</param>
243         /// <param name="second">The second byte array value to compare</param>
244         /// <returns>
245         ///   <c>true</c> if both arrays are <c>null</c>, or if both arrays are of
246         ///   the same length and contain the same byte values; otherwise <c>false</c>.
247         /// </returns>
248         protected internal static bool BinaryEquals(byte[] first, byte[] second)
249         {
250             if (object.ReferenceEquals(first, second))
251             {
252                 return true;
253             }
254
255             if (first == null || second == null)
256             {
257                 return false;
258             }
259
260             return ByValueEqualityComparer.CompareBinaryValues(first, second);
261         }
262
263         /// <summary>
264         /// Duplicates the current byte value.
265         /// </summary>
266         /// <param name="currentValue">
267         /// The current byte array value
268         /// </param>
269         /// <returns>
270         /// Must return a copy of the values because byte arrays are mutable without providing a
271         /// reliable mechanism for us to track changes.  This allows us to treat byte arrays like
272         /// structs which is at least a somewhat understood mechanism.
273         /// </returns>
274         protected internal static byte[] GetValidValue(byte[] currentValue)
275         {
276             if (currentValue == null)
277             {
278                 return null;
279             }
280             return (byte[])currentValue.Clone();
281         }
282
283         /// <summary>
284         /// Makes sure the Byte [] value being set for a property is valid.
285         /// </summary>
286         /// <param name="value">
287         /// The value passed into the property setter.
288         /// </param>
289         /// <param name="isNullable">
290         /// Flag indicating if this property is allowed to be null.
291         /// </param>
292         /// <param name="propertyName">
293         /// Name of the property that is being validated.
294         /// </param>
295         /// <returns>
296         /// Returns the value if valid.
297         /// </returns>
298         /// <exception cref="System.Data.ConstraintException">
299         /// If value is null for a non nullable value.
300         /// </exception>
301         protected internal static Byte[] SetValidValue(Byte[] value, bool isNullable, string propertyName)
302         {
303             if (value == null)
304             {
305                 if (!isNullable)
306                 {
307                     EntityUtil.ThrowPropertyIsNotNullable(propertyName);
308                 }
309                 return value;
310             }
311             return (byte[])value.Clone();
312         }
313
314         /// <summary>
315         /// Makes sure the Byte [] value being set for a property is valid.
316         /// </summary>
317         /// <param name="value">
318         /// The value passed into the property setter.
319         /// </param>
320         /// <param name="isNullable">
321         /// Flag indicating if this property is allowed to be null.
322         /// </param>
323         /// <returns>
324         /// Returns the value if valid.
325         /// </returns>
326         /// <exception cref="System.Data.ConstraintException">
327         /// If value is null for a non nullable value.
328         /// </exception>
329         protected internal static Byte[] SetValidValue(Byte[] value, bool isNullable)
330         {
331             return SetValidValue(value, isNullable, null);
332         }
333
334         /// <summary>
335         /// Makes sure the boolean value being set for a property is valid.
336         /// </summary>
337         /// <param name="value">
338         /// Boolean value.
339         /// </param>
340         /// <param name="propertyName">
341         /// Name of the property that is being validated.
342         /// </param>
343         /// <returns>
344         /// The Boolean value.
345         /// </returns>
346         protected internal static bool SetValidValue(bool value, string propertyName)
347         {
348             // no checks yet
349             return value;
350         }
351
352         /// <summary>
353         /// Makes sure the boolean value being set for a property is valid.
354         /// </summary>
355         /// <param name="value">
356         /// Boolean value.
357         /// </param>
358         /// <returns>
359         /// The Boolean value.
360         /// </returns>
361         protected internal static bool SetValidValue(bool value)
362         {
363             // no checks yet
364             return value;
365         }
366
367         /// <summary>
368         /// Makes sure the boolean value being set for a property is valid.
369         /// </summary>
370         /// <param name="value">
371         /// Boolean value
372         /// </param>
373         /// <param name="propertyName">
374         /// Name of the property that is being validated.
375         /// </param>
376         /// <returns>
377         /// The Boolean value.
378         /// </returns>
379         protected internal static Nullable<bool> SetValidValue(Nullable<bool> value, string propertyName)
380         {
381             // no checks yet
382             return value;
383         }
384
385         /// <summary>
386         /// Makes sure the boolean value being set for a property is valid.
387         /// </summary>
388         /// <param name="value">
389         /// Boolean value
390         /// </param>
391         /// <returns>
392         /// The Boolean value.
393         /// </returns>
394         protected internal static Nullable<bool> SetValidValue(Nullable<bool> value)
395         {
396             // no checks yet
397             return value;
398         }
399
400         /// <summary>
401         /// Makes sure the byte value being set for a property is valid.
402         /// </summary>
403         /// <param name="value">
404         /// Byte value
405         /// </param>
406         /// <param name="propertyName">
407         /// Name of the property that is being validated.
408         /// </param>
409         /// <returns>
410         /// The Byte value.
411         /// </returns>
412         protected internal static byte SetValidValue(byte value, string propertyName)
413         {
414             // no checks yet
415             return value;
416         }
417
418         /// <summary>
419         /// Makes sure the byte value being set for a property is valid.
420         /// </summary>
421         /// <param name="value">
422         /// Byte value
423         /// </param>
424         /// <returns>
425         /// The Byte value.
426         /// </returns>
427         protected internal static byte SetValidValue(byte value)
428         {
429             // no checks yet
430             return value;
431         }
432
433         /// <summary>
434         /// Makes sure the byte value being set for a property is valid.
435         /// </summary>
436         /// <param name="value">
437         /// Byte value
438         /// </param>
439         /// <param name="propertyName">
440         /// Name of the property that is being validated.
441         /// </param>
442         /// <returns>
443         /// The Byte value.
444         /// </returns>
445         protected internal static Nullable<byte> SetValidValue(Nullable<byte> value, string propertyName)
446         {
447             // no checks yet
448             return value;
449         }
450
451         /// <summary>
452         /// Makes sure the byte value being set for a property is valid.
453         /// </summary>
454         /// <param name="value">
455         /// Byte value
456         /// </param>
457         /// <returns>
458         /// The Byte value.
459         /// </returns>
460         protected internal static Nullable<byte> SetValidValue(Nullable<byte> value)
461         {
462             // no checks yet
463             return value;
464         }
465
466         /// <summary>
467         /// Makes sure the sbyte value being set for a property is valid.
468         /// </summary>
469         /// <param name="value">
470         /// sbyte value
471         /// </param>
472         /// <param name="propertyName">
473         /// Name of the property that is being validated.
474         /// </param>
475         /// <returns>
476         /// The sbyte value.
477         /// </returns>
478         [CLSCompliant(false)]
479         protected internal static sbyte SetValidValue(sbyte value, string propertyName)
480         {
481             // no checks yet
482             return value;
483         }
484
485  
486         /// <summary>
487         /// Makes sure the sbyte value being set for a property is valid.
488         /// </summary>
489         /// <param name="value">
490         /// sbyte value
491         /// </param>
492         /// <returns>
493         /// The sbyte value.
494         /// </returns>
495         [CLSCompliant(false)]
496         protected internal static sbyte SetValidValue(sbyte value)
497         {
498             // no checks yet
499             return value;
500         }
501
502         /// <summary>
503         /// Makes sure the sbyte value being set for a property is valid.
504         /// </summary>
505         /// <param name="value">
506         /// sbyte value
507         /// </param>
508         /// <param name="propertyName">
509         /// Name of the property that is being validated.
510         /// </param>
511         /// <returns>
512         /// The sbyte value.
513         /// </returns>
514         [CLSCompliant(false)]
515         protected internal static Nullable<sbyte> SetValidValue(Nullable<sbyte> value, string propertyName)
516         {
517             // no checks yet
518             return value;
519         }
520
521
522         /// <summary>
523         /// Makes sure the sbyte value being set for a property is valid.
524         /// </summary>
525         /// <param name="value">
526         /// sbyte value
527         /// </param>
528         /// <returns>
529         /// The sbyte value.
530         /// </returns>
531         [CLSCompliant(false)]
532         protected internal static Nullable<sbyte> SetValidValue(Nullable<sbyte> value)
533         {
534             // no checks yet
535             return value;
536         }
537
538         /// <summary>
539         /// Makes sure the datetime value being set for a property is valid.
540         /// </summary>
541         /// <param name="value">
542         /// datetime value
543         /// </param>
544         /// <param name="propertyName">
545         /// Name of the property that is being validated.
546         /// </param>
547         /// <returns>
548         /// The datetime value.
549         /// </returns>
550         protected internal static DateTime SetValidValue(DateTime value, string propertyName)
551         {
552             // no checks yet
553             return value;
554         }
555
556
557         /// <summary>
558         /// Makes sure the datetime value being set for a property is valid.
559         /// </summary>
560         /// <param name="value">
561         /// datetime value
562         /// </param>
563         /// <returns>
564         /// The datetime value.
565         /// </returns>
566         protected internal static DateTime SetValidValue(DateTime value)
567         {
568             // no checks yet
569             return value;
570         }
571
572         /// <summary>
573         /// Makes sure the datetime value being set for a property is valid.
574         /// </summary>
575         /// <param name="value">
576         /// datetime value
577         /// </param>
578         /// <param name="propertyName">
579         /// Name of the property that is being validated.
580         /// </param>
581         /// <returns>
582         /// The datetime value.
583         /// </returns>
584         protected internal static Nullable<DateTime> SetValidValue(Nullable<DateTime> value, string propertyName)
585         {
586             // no checks yet
587             return value;
588         }
589
590
591         /// <summary>
592         /// Makes sure the datetime value being set for a property is valid.
593         /// </summary>
594         /// <param name="value">
595         /// datetime value
596         /// </param>
597         /// <returns>
598         /// The datetime value.
599         /// </returns>
600         protected internal static Nullable<DateTime> SetValidValue(Nullable<DateTime> value)
601         {
602             // no checks yet
603             return value;
604         }
605
606         /// <summary>
607         /// Makes sure the timespan value being set for a property is valid.
608         /// </summary>
609         /// <param name="value">
610         /// timespan value
611         /// </param>
612         /// <param name="propertyName">
613         /// Name of the property that is being validated.
614         /// </param>
615         /// <returns>
616         /// The timspan value.
617         /// </returns>
618         protected internal static TimeSpan SetValidValue(TimeSpan value, string propertyName)
619         {
620             // no checks yet
621             return value;
622         }
623
624
625         /// <summary>
626         /// Makes sure the timespan value being set for a property is valid.
627         /// </summary>
628         /// <param name="value">
629         /// timespan value
630         /// </param>
631         /// <returns>
632         /// The timspan value.
633         /// </returns>
634         protected internal static TimeSpan SetValidValue(TimeSpan value)
635         {
636             // no checks yet
637             return value;
638         }
639
640         /// <summary>
641         /// Makes sure the TimeSpan value being set for a property is valid.
642         /// </summary>
643         /// <param name="value">
644         /// timespan value
645         /// </param>
646         /// <param name="propertyName">
647         /// Name of the property that is being validated.
648         /// </param>
649         /// <returns>
650         /// The timespan value.
651         /// </returns>
652         protected internal static Nullable<TimeSpan> SetValidValue(Nullable<TimeSpan> value, string propertyName)
653         {
654             // no checks yet
655             return value;
656         }
657
658
659         /// <summary>
660         /// Makes sure the TimeSpan value being set for a property is valid.
661         /// </summary>
662         /// <param name="value">
663         /// timespan value
664         /// </param>
665         /// <returns>
666         /// The timespan value.
667         /// </returns>
668         protected internal static Nullable<TimeSpan> SetValidValue(Nullable<TimeSpan> value)
669         {
670             // no checks yet
671             return value;
672         }
673
674         /// <summary>
675         /// Makes sure the datetimeoffset value being set for a property is valid.
676         /// </summary>
677         /// <param name="value">
678         /// datetimeoffset value
679         /// </param>
680         /// <param name="propertyName">
681         /// Name of the property that is being validated.
682         /// </param>
683         /// <returns>
684         /// The datetimeoffset value.
685         /// </returns>
686         protected internal static DateTimeOffset SetValidValue(DateTimeOffset value, string propertyName)
687         {
688             // no checks yet
689             return value;
690         }
691
692
693         /// <summary>
694         /// Makes sure the datetimeoffset value being set for a property is valid.
695         /// </summary>
696         /// <param name="value">
697         /// datetimeoffset value
698         /// </param>
699         /// <returns>
700         /// The datetimeoffset value.
701         /// </returns>
702         protected internal static DateTimeOffset SetValidValue(DateTimeOffset value)
703         {
704             // no checks yet
705             return value;
706         }
707
708         /// <summary>
709         /// Makes sure the datetimeoffset value being set for a property is valid.
710         /// </summary>
711         /// <param name="value">
712         /// datetimeoffset value
713         /// </param>
714         /// <param name="propertyName">
715         /// Name of the property that is being validated.
716         /// </param>
717         /// <returns>
718         /// The datetimeoffset value.
719         /// </returns>
720         protected internal static Nullable<DateTimeOffset> SetValidValue(Nullable<DateTimeOffset> value, string propertyName)
721         {
722             // no checks yet
723             return value;
724         }
725
726
727         /// <summary>
728         /// Makes sure the datetimeoffset value being set for a property is valid.
729         /// </summary>
730         /// <param name="value">
731         /// datetimeoffset value
732         /// </param>
733         /// <returns>
734         /// The datetimeoffset value.
735         /// </returns>
736         protected internal static Nullable<DateTimeOffset> SetValidValue(Nullable<DateTimeOffset> value)
737         {
738             // no checks yet
739             return value;
740         }
741
742         /// <summary>
743         /// Ensure that the input is a valid decimal value
744         /// </summary>
745         /// <param name="value">
746         /// decimal value.
747         /// </param>
748         /// <param name="propertyName">
749         /// Name of the property that is being validated.
750         /// </param>
751         /// <returns>
752         /// The decimal value.
753         /// </returns>
754         protected internal static Decimal SetValidValue(Decimal value, string propertyName)
755         {
756             // no checks yet
757             return value;
758         }
759
760
761         /// <summary>
762         /// Ensure that the input is a valid decimal value
763         /// </summary>
764         /// <param name="value">
765         /// proposed value
766         /// </param>
767         /// <returns>new value</returns>
768         protected internal static Decimal SetValidValue(Decimal value)
769         {
770             // no checks yet
771             return value;
772         }
773
774         /// <summary>
775         /// Ensure that the input is a valid decimal value
776         /// </summary>
777         /// <param name="value">
778         /// decimal value.
779         /// </param>
780         /// <param name="propertyName">
781         /// Name of the property that is being validated.
782         /// </param>
783         /// <returns>
784         /// The decimal value.
785         /// </returns>
786         protected internal static Nullable<Decimal> SetValidValue(Nullable<Decimal> value, string propertyName)
787         {
788             // no checks yet
789             return value;
790         }
791         
792
793         /// <summary>
794         /// Ensure that the input is a valid decimal value
795         /// </summary>
796         /// <param name="value">
797         /// decimal value.
798         /// </param>
799         /// <returns>
800         /// The decimal value.
801         /// </returns>
802         protected internal static Nullable<Decimal> SetValidValue(Nullable<Decimal> value)
803         {
804             // no checks yet
805             return value;
806         }
807
808         /// <summary>
809         /// Makes sure the double value being set for a property is valid.
810         /// </summary>
811         /// <param name="value">
812         /// double value
813         /// </param>
814         /// <param name="propertyName">
815         /// Name of the property that is being validated.
816         /// </param>
817         /// <returns>
818         /// the double value
819         /// </returns>
820         protected internal static double SetValidValue(double value, string propertyName)
821         {
822             // no checks yet
823             return value;
824         }
825
826         
827         /// <summary>
828         /// Makes sure the double value being set for a property is valid.
829         /// </summary>
830         /// <param name="value">
831         /// double value
832         /// </param>
833         /// <returns>
834         /// the double value
835         /// </returns>
836         protected internal static double SetValidValue(double value)
837         {
838             // no checks yet
839             return value;
840         }
841
842         /// <summary>
843         /// Makes sure the double value being set for a property is valid.
844         /// </summary>
845         /// <param name="value">
846         /// double value
847         /// </param>
848         /// <param name="propertyName">
849         /// Name of the property that is being validated.
850         /// </param>
851         /// <returns>
852         /// the double value
853         /// </returns>
854         protected internal static Nullable<double> SetValidValue(Nullable<double> value, string propertyName)
855         {
856             // no checks yet
857             return value;
858         }
859
860
861         /// <summary>
862         /// Makes sure the double value being set for a property is valid.
863         /// </summary>
864         /// <param name="value">
865         /// double value
866         /// </param>
867         /// <returns>
868         /// the double value
869         /// </returns>
870         protected internal static Nullable<double> SetValidValue(Nullable<double> value)
871         {
872             // no checks yet
873             return value;
874         }
875
876         /// <summary>
877         /// Makes sure the Single value being set for a property is valid.
878         /// </summary>
879         /// <param name="value">
880         /// float value
881         /// </param>
882         /// <param name="propertyName">
883         /// Name of the property that is being validated.
884         /// </param>
885         /// <returns>
886         /// the float value.
887         /// </returns>
888         protected internal static float SetValidValue(Single value, string propertyName)
889         {
890             // no checks yet
891             return value;
892         }
893
894
895         /// <summary>
896         /// Makes sure the Single value being set for a property is valid.
897         /// </summary>
898         /// <param name="value">
899         /// float value
900         /// </param>
901         /// <returns>
902         /// the float value.
903         /// </returns>
904         protected internal static float SetValidValue(Single value)
905         {
906             // no checks yet
907             return value;
908         }
909
910         /// <summary>
911         /// Makes sure the Single value being set for a property is valid.
912         /// </summary>
913         /// <param name="value">
914         /// nullable Single value
915         /// </param>
916         /// <param name="propertyName">
917         /// Name of the property that is being validated.
918         /// </param>
919         /// <returns>
920         /// the nullable Single value
921         /// </returns>
922         protected internal static Nullable<Single> SetValidValue(Nullable<Single> value, string propertyName)
923         {
924             // no checks yet
925             return value;
926         }
927
928
929         /// <summary>
930         /// Makes sure the Single value being set for a property is valid.
931         /// </summary>
932         /// <param name="value">
933         /// nullable Single value
934         /// </param>
935         /// <returns>
936         /// the nullable Single value
937         /// </returns>
938         protected internal static Nullable<Single> SetValidValue(Nullable<Single> value)
939         {
940             // no checks yet
941             return value;
942         }
943
944         /// <summary>
945         /// Makes sure the Guid value being set for a property is valid.
946         /// </summary>
947         /// <param name="value">
948         /// Guid value
949         /// </param>
950         /// <param name="propertyName">
951         /// Name of the property that is being validated.
952         /// </param>
953         /// <returns>
954         /// The Guid value
955         /// </returns>
956         protected internal static Guid SetValidValue(Guid value, string propertyName)
957         {
958             // no checks yet
959             return value;
960         }
961
962
963         /// <summary>
964         /// Makes sure the Guid value being set for a property is valid.
965         /// </summary>
966         /// <param name="value">
967         /// Guid value
968         /// </param>
969         /// <returns>
970         /// The Guid value
971         /// </returns>
972         protected internal static Guid SetValidValue(Guid value)
973         {
974             // no checks yet
975             return value;
976         }
977
978         /// <summary>
979         /// Makes sure the Guid value being set for a property is valid.
980         /// </summary>
981         /// <param name="value">
982         /// nullable Guid value
983         /// </param>
984         /// <param name="propertyName">
985         /// Name of the property that is being validated.
986         /// </param>
987         /// <returns>
988         /// The nullable Guid value
989         /// </returns>
990         protected internal static Nullable<Guid> SetValidValue(Nullable<Guid> value, string propertyName)
991         {
992             // no checks yet
993             return value;
994         }
995
996
997         /// <summary>
998         /// Makes sure the Guid value being set for a property is valid.
999         /// </summary>
1000         /// <param name="value">
1001         /// nullable Guid value
1002         /// </param>
1003         /// <returns>
1004         /// The nullable Guid value
1005         /// </returns>
1006         protected internal static Nullable<Guid> SetValidValue(Nullable<Guid> value)
1007         {
1008             // no checks yet
1009             return value;
1010         }
1011
1012         /// <summary>
1013         /// Makes sure the Int16 value being set for a property is valid.
1014         /// </summary>
1015         /// <param name="value">
1016         /// Int16 value
1017         /// </param>
1018         /// <param name="propertyName">
1019         /// Name of the property that is being validated.
1020         /// </param>
1021         /// <returns>
1022         /// The Int16 value
1023         /// </returns>
1024         protected internal static Int16 SetValidValue(Int16 value, string propertyName)
1025         {
1026             // no checks yet
1027             return value;
1028         }
1029
1030
1031         /// <summary>
1032         /// Makes sure the Int16 value being set for a property is valid.
1033         /// </summary>
1034         /// <param name="value">
1035         /// Int16 value
1036         /// </param>
1037         /// <returns>
1038         /// The Int16 value
1039         /// </returns>
1040         protected internal static Int16 SetValidValue(Int16 value)
1041         {
1042             // no checks yet
1043             return value;
1044         }
1045
1046         /// <summary>
1047         /// Makes sure the Int16 value being set for a property is valid.
1048         /// </summary>
1049         /// <param name="value">
1050         /// nullable Int16
1051         /// </param>
1052         /// <param name="propertyName">
1053         /// Name of the property that is being validated.
1054         /// </param>
1055         /// <returns>
1056         /// The Int16 value
1057         /// </returns>
1058         protected internal static Nullable<Int16> SetValidValue(Nullable<Int16> value, string propertyName)
1059         {
1060             // no checks yet
1061             return value;
1062         }
1063
1064
1065         /// <summary>
1066         /// Makes sure the Int16 value being set for a property is valid.
1067         /// </summary>
1068         /// <param name="value">
1069         /// nullable Int16
1070         /// </param>
1071         /// <returns>
1072         /// The Int16 value
1073         /// </returns>
1074         protected internal static Nullable<Int16> SetValidValue(Nullable<Int16> value)
1075         {
1076             // no checks yet
1077             return value;
1078         }
1079
1080         /// <summary>
1081         /// Makes sure the Int32 value being set for a property is valid.
1082         /// </summary>
1083         /// <param name="value">
1084         /// Int32 value
1085         /// </param>
1086         /// <param name="propertyName">
1087         /// Name of the property that is being validated.
1088         /// </param>
1089         /// <returns>
1090         /// The Int32 value
1091         /// </returns>
1092         protected internal static Int32 SetValidValue(Int32 value, string propertyName)
1093         {
1094             // no checks yet
1095             return value;
1096         }
1097
1098
1099         /// <summary>
1100         /// Makes sure the Int32 value being set for a property is valid.
1101         /// </summary>
1102         /// <param name="value">
1103         /// Int32 value
1104         /// </param>
1105         /// <returns>
1106         /// The Int32 value
1107         /// </returns>
1108         protected internal static Int32 SetValidValue(Int32 value)
1109         {
1110             // no checks yet
1111             return value;
1112         }
1113
1114         /// <summary>
1115         /// Makes sure the Int32 value being set for a property is valid.
1116         /// </summary>
1117         /// <param name="value">
1118         /// nullable Int32 value
1119         /// </param>
1120         /// <param name="propertyName">
1121         /// Name of the property that is being validated.
1122         /// </param>
1123         /// <returns>
1124         /// The nullable Int32</returns>
1125         protected internal static Nullable<Int32> SetValidValue(Nullable<Int32> value, string propertyName)
1126         {
1127             // no checks yet
1128             return value;
1129         }
1130
1131
1132         /// <summary>
1133         /// Makes sure the Int32 value being set for a property is valid.
1134         /// </summary>
1135         /// <param name="value">
1136         /// nullable Int32 value
1137         /// </param>
1138         /// <returns>
1139         /// The nullable Int32</returns>
1140         protected internal static Nullable<Int32> SetValidValue(Nullable<Int32> value)
1141         {
1142             // no checks yet
1143             return value;
1144         }
1145
1146         /// <summary>
1147         /// Makes sure the Int64 value being set for a property is valid.
1148         /// </summary>
1149         /// <param name="value">
1150         /// Int64 value
1151         /// </param>
1152         /// <param name="propertyName">
1153         /// Name of the property that is being validated.
1154         /// </param>
1155         /// <returns>
1156         /// The Int64 value
1157         /// </returns>
1158         protected internal static Int64 SetValidValue(Int64 value, string propertyName)
1159         {
1160             // no checks yet
1161             return value;
1162         }
1163
1164
1165         /// <summary>
1166         /// Makes sure the Int64 value being set for a property is valid.
1167         /// </summary>
1168         /// <param name="value">
1169         /// Int64 value
1170         /// </param>
1171         /// <returns>
1172         /// The Int64 value
1173         /// </returns>
1174         protected internal static Int64 SetValidValue(Int64 value)
1175         {
1176             // no checks yet
1177             return value;
1178         }
1179
1180         /// <summary>
1181         /// Makes sure the Int64 value being set for a property is valid.
1182         /// </summary>
1183         /// <param name="value">
1184         /// nullable Int64 value
1185         /// </param>
1186         /// <param name="propertyName">
1187         /// Name of the property that is being validated.
1188         /// </param>
1189         /// <returns>
1190         /// The nullable Int64 value
1191         /// </returns>
1192         protected internal static Nullable<Int64> SetValidValue(Nullable<Int64> value, string propertyName)
1193         {
1194             // no checks yet
1195             return value;
1196         }
1197
1198
1199         /// <summary>
1200         /// Makes sure the Int64 value being set for a property is valid.
1201         /// </summary>
1202         /// <param name="value">
1203         /// nullable Int64 value
1204         /// </param>
1205         /// <returns>
1206         /// The nullable Int64 value
1207         /// </returns>
1208         protected internal static Nullable<Int64> SetValidValue(Nullable<Int64> value)
1209         {
1210             // no checks yet
1211             return value;
1212         }
1213
1214         /// <summary>
1215         /// Makes sure the UInt16 value being set for a property is valid.
1216         /// </summary>
1217         /// <param name="value">
1218         /// UInt16 value
1219         /// </param>
1220         /// <param name="propertyName">
1221         /// Name of the property that is being validated.
1222         /// </param>
1223         /// <returns>
1224         /// The UInt16 value
1225         /// </returns>
1226         [CLSCompliant(false)]
1227         protected internal static UInt16 SetValidValue(UInt16 value, string propertyName)
1228         {
1229             // no checks yet
1230             return value;
1231         }
1232
1233
1234         /// <summary>
1235         /// Makes sure the UInt16 value being set for a property is valid.
1236         /// </summary>
1237         /// <param name="value">
1238         /// UInt16 value
1239         /// </param>
1240         /// <returns>
1241         /// The UInt16 value
1242         /// </returns>
1243         [CLSCompliant(false)]
1244         protected internal static UInt16 SetValidValue(UInt16 value)
1245         {
1246             // no checks yet
1247             return value;
1248         }
1249
1250         /// <summary>
1251         /// Makes sure the UInt16 value being set for a property is valid.
1252         /// </summary>
1253         /// <param name="value">
1254         /// nullable UInt16 value
1255         /// </param>
1256         /// <param name="propertyName">
1257         /// Name of the property that is being validated.
1258         /// </param>
1259         /// <returns>
1260         /// The nullable UInt16 value
1261         /// </returns>
1262         [CLSCompliant(false)]
1263         protected internal static Nullable<UInt16> SetValidValue(Nullable<UInt16> value, string propertyName)
1264         {
1265             // no checks yet
1266             return value;
1267         }
1268
1269
1270         /// <summary>
1271         /// Makes sure the UInt16 value being set for a property is valid.
1272         /// </summary>
1273         /// <param name="value">
1274         /// nullable UInt16 value
1275         /// </param>
1276         /// <returns>
1277         /// The nullable UInt16 value
1278         /// </returns>
1279         [CLSCompliant(false)]
1280         protected internal static Nullable<UInt16> SetValidValue(Nullable<UInt16> value)
1281         {
1282             // no checks yet
1283             return value;
1284         }
1285
1286         /// <summary>
1287         /// Makes sure the UInt32 value being set for a property is valid.
1288         /// </summary>
1289         /// <param name="value">
1290         /// UInt32 value
1291         /// </param>
1292         /// <param name="propertyName">
1293         /// Name of the property that is being validated.
1294         /// </param>
1295         /// <returns>
1296         /// The UInt32 value
1297         /// </returns>
1298         [CLSCompliant(false)]
1299         protected internal static UInt32 SetValidValue(UInt32 value, string propertyName)
1300         {
1301             // no checks yet
1302             return value;
1303         }
1304
1305
1306         /// <summary>
1307         /// Makes sure the UInt32 value being set for a property is valid.
1308         /// </summary>
1309         /// <param name="value">
1310         /// UInt32 value
1311         /// </param>
1312         /// <returns>
1313         /// The UInt32 value
1314         /// </returns>
1315         [CLSCompliant(false)]
1316         protected internal static UInt32 SetValidValue(UInt32 value)
1317         {
1318             // no checks yet
1319             return value;
1320         }
1321
1322         /// <summary>
1323         /// Makes sure the UInt32 value being set for a property is valid.
1324         /// </summary>
1325         /// <param name="value">
1326         /// nullable UInt32 value
1327         /// </param>
1328         /// <param name="propertyName">
1329         /// Name of the property that is being validated.
1330         /// </param>
1331         /// <returns>
1332         /// The nullable UInt32 value
1333         /// </returns>
1334         [CLSCompliant(false)]
1335         protected internal static Nullable<UInt32> SetValidValue(Nullable<UInt32> value, string propertyName)
1336         {
1337             // no checks yet
1338             return value;
1339         }
1340
1341
1342         /// <summary>
1343         /// Makes sure the UInt32 value being set for a property is valid.
1344         /// </summary>
1345         /// <param name="value">
1346         /// nullable UInt32 value
1347         /// </param>
1348         /// <returns>
1349         /// The nullable UInt32 value
1350         /// </returns>
1351         [CLSCompliant(false)]
1352         protected internal static Nullable<UInt32> SetValidValue(Nullable<UInt32> value)
1353         {
1354             // no checks yet
1355             return value;
1356         }
1357
1358         /// <summary>
1359         /// Makes sure the UInt64 value being set for a property is valid.
1360         /// </summary>
1361         /// <param name="value">
1362         /// UInt64 value
1363         /// </param>
1364         /// <param name="propertyName">
1365         /// Name of the property that is being validated.
1366         /// </param>
1367         /// <returns>
1368         /// The UInt64 value
1369         /// </returns>
1370         [CLSCompliant(false)]
1371         protected internal static UInt64 SetValidValue(UInt64 value, string propertyName)
1372         {
1373             // no checks yet
1374             return value;
1375         }
1376
1377
1378         /// <summary>
1379         /// Makes sure the UInt64 value being set for a property is valid.
1380         /// </summary>
1381         /// <param name="value">
1382         /// UInt64 value
1383         /// </param>
1384         /// <returns>
1385         /// The UInt64 value
1386         /// </returns>
1387         [CLSCompliant(false)]
1388         protected internal static UInt64 SetValidValue(UInt64 value)
1389         {
1390             // no checks yet
1391             return value;
1392         }
1393
1394         /// <summary>
1395         /// Makes sure the UInt64 value being set for a property is valid.
1396         /// </summary>
1397         /// <param name="value">
1398         /// nullable UInt64 value
1399         /// </param>
1400         /// <param name="propertyName">
1401         /// Name of the property that is being validated.
1402         /// </param>
1403         /// <returns>
1404         /// The nullable UInt64 value
1405         /// </returns>
1406         [CLSCompliant(false)]
1407         protected internal static Nullable<UInt64> SetValidValue(Nullable<UInt64> value, string propertyName)
1408         {
1409             // no checks yet
1410             return value;
1411         }
1412
1413
1414         /// <summary>
1415         /// Makes sure the UInt64 value being set for a property is valid.
1416         /// </summary>
1417         /// <param name="value">
1418         /// nullable UInt64 value
1419         /// </param>
1420         /// <returns>
1421         /// The nullable UInt64 value
1422         /// </returns>
1423         [CLSCompliant(false)]
1424         protected internal static Nullable<UInt64> SetValidValue(Nullable<UInt64> value)
1425         {
1426             // no checks yet
1427             return value;
1428         }
1429
1430         /// <summary>
1431         /// Validates that the property is not longer than allowed, and throws if it is
1432         /// </summary>
1433         /// <param name="value">
1434         /// string value to be checked.
1435         /// </param>
1436         /// <param name="isNullable">
1437         /// Flag indicating if this property is allowed to be null.
1438         /// </param>
1439         /// <param name="propertyName">
1440         /// Name of the property that is being validated.
1441         /// </param>
1442         /// <exception cref="System.Data.ConstraintException">
1443         /// The string value is null for a non-nullable string
1444         /// </exception>
1445         protected internal static string SetValidValue(string value, bool isNullable, string propertyName)
1446         {
1447             if (value == null)
1448             {
1449                 if (!isNullable)
1450                 {
1451                     EntityUtil.ThrowPropertyIsNotNullable(propertyName);
1452                 }
1453             }
1454             return value;
1455         }
1456
1457
1458         /// <summary>
1459         /// Validates that the property is not longer than allowed, and throws if it is
1460         /// </summary>
1461         /// <param name="value">
1462         /// string value to be checked.
1463         /// </param>
1464         /// <param name="isNullable">
1465         /// Flag indicating if this property is allowed to be null.
1466         /// </param>
1467         /// <exception cref="System.Data.ConstraintException">
1468         /// The string value is null for a non-nullable string
1469         /// </exception>
1470         protected internal static string SetValidValue(string value, bool isNullable)
1471         {
1472             return SetValidValue(value, isNullable, null);
1473         }
1474
1475         /// <summary>
1476         /// Validates that the property is not null, and throws if it is
1477         /// </summary>
1478         /// <param name="value">
1479         /// <see cref="System.Data.Spatial.DbGeography"/> value to be checked.
1480         /// </param>
1481         /// <param name="isNullable">
1482         /// Flag indicating if this property is allowed to be null.
1483         /// </param>
1484         /// <param name="propertyName">
1485         /// Name of the property that is being validated.
1486         /// </param>
1487         /// <exception cref="System.Data.ConstraintException">
1488         /// The value is null for a non-nullable property
1489         /// </exception>
1490         protected internal static System.Data.Spatial.DbGeography SetValidValue(System.Data.Spatial.DbGeography value, bool isNullable, string propertyName)
1491         {
1492             if (value == null)
1493             {
1494                 if (!isNullable)
1495                 {
1496                     EntityUtil.ThrowPropertyIsNotNullable(propertyName);
1497                 }
1498             }
1499             return value;
1500         }
1501
1502
1503         /// <summary>
1504         /// Validates that the property is not null, and throws if it is
1505         /// </summary>
1506         /// <param name="value">
1507         /// <see cref="System.Data.Spatial.DbGeography"/> value to be checked.
1508         /// </param>
1509         /// <param name="isNullable">
1510         /// Flag indicating if this property is allowed to be null.
1511         /// </param>
1512         /// <exception cref="System.Data.ConstraintException">
1513         /// The value is null for a non-nullable property
1514         /// </exception>
1515         protected internal static System.Data.Spatial.DbGeography SetValidValue(System.Data.Spatial.DbGeography value, bool isNullable)
1516         {
1517             return SetValidValue(value, isNullable, null);
1518         }
1519
1520         /// <summary>
1521         /// Validates that the property is not null, and throws if it is
1522         /// </summary>
1523         /// <param name="value">
1524         /// <see cref="System.Data.Spatial.DbGeometry"/> value to be checked.
1525         /// </param>
1526         /// <param name="isNullable">
1527         /// Flag indicating if this property is allowed to be null.
1528         /// </param>
1529         /// <param name="propertyName">
1530         /// Name of the property that is being validated.
1531         /// </param>
1532         /// <exception cref="System.Data.ConstraintException">
1533         /// The value is null for a non-nullable property
1534         /// </exception>
1535         protected internal static System.Data.Spatial.DbGeometry SetValidValue(System.Data.Spatial.DbGeometry value, bool isNullable, string propertyName)
1536         {
1537             if (value == null)
1538             {
1539                 if (!isNullable)
1540                 {
1541                     EntityUtil.ThrowPropertyIsNotNullable(propertyName);
1542                 }
1543             }
1544             return value;
1545         }
1546
1547
1548         /// <summary>
1549         /// Validates that the property is not null, and throws if it is
1550         /// </summary>
1551         /// <param name="value">
1552         /// <see cref="System.Data.Spatial.DbGeometry"/> value to be checked.
1553         /// </param>
1554         /// <param name="isNullable">
1555         /// Flag indicating if this property is allowed to be null.
1556         /// </param>
1557         /// <exception cref="System.Data.ConstraintException">
1558         /// The value is null for a non-nullable property
1559         /// </exception>
1560         protected internal static System.Data.Spatial.DbGeometry SetValidValue(System.Data.Spatial.DbGeometry value, bool isNullable)
1561         {
1562             return SetValidValue(value, isNullable, null);
1563         }
1564
1565         /// <summary>
1566         /// Set a whole ComplexObject on an Entity or another ComplexObject
1567         /// </summary>  
1568         /// <remarks>
1569         /// Unlike most of the other SetValidValue methods, this one is not static
1570         /// because it uses a reference to this in order to set the parent reference for the complex object.
1571         /// </remarks>
1572         /// <param name="oldValue">
1573         /// The current value that is set.
1574         /// </param>
1575         /// <param name="newValue">
1576         /// The new value that will be set.
1577         /// </param>
1578         /// <param name="property">
1579         /// The name of the complex type property that is being set.
1580         /// </param>        
1581         /// <returns>
1582         /// The new value of the complex type property
1583         /// </returns>
1584         protected internal T SetValidValue<T>(T oldValue, T newValue, string property) where T : ComplexObject
1585         {
1586             // Nullable complex types are not supported in v1, but we allow setting null here if the parent entity is detached
1587             if (newValue == null && IsChangeTracked)
1588             {
1589                 throw EntityUtil.NullableComplexTypesNotSupported(property);
1590             }
1591
1592             if (oldValue != null)
1593             {
1594                 oldValue.DetachFromParent();
1595             }
1596
1597             if (newValue != null)
1598             {
1599                 newValue.AttachToParent(this, property);
1600             }    
1601             
1602             return newValue;
1603         }
1604
1605         /// <summary>
1606         /// Helper method used in entity/complex object factory methods to verify that a complex object is not null
1607         /// </summary>
1608         /// <typeparam name="TComplex">Type of the complex property</typeparam>
1609         /// <param name="complexObject">Complex object being verified</param>
1610         /// <param name="propertyName">Property name associated with this complex object</param>
1611         /// <returns>the same complex object that was passed in, if an exception didn't occur</returns>
1612         protected internal static TComplex VerifyComplexObjectIsNotNull<TComplex>(TComplex complexObject, string propertyName) where TComplex : ComplexObject
1613         {
1614             if (complexObject == null)
1615             {
1616                 EntityUtil.ThrowPropertyIsNotNullable(propertyName);
1617             }
1618             return complexObject;
1619         }
1620         #endregion
1621     }
1622 }