Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Web.Entity / System / Data / WebControls / EntityDataSource.cs
1 //---------------------------------------------------------------------
2 // <copyright file="EntityDataSource.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       [....]
7 // @backupOwner [....]
8 //---------------------------------------------------------------------
9 using System;
10 using System.Collections;
11 using System.Data;
12 using System.Data.Common;
13 using System.Data.Objects;
14 using System.Data.Metadata.Edm;
15 using System.Configuration;
16 using System.Diagnostics;
17 using System.Linq;
18 using System.Reflection;
19 using System.Web;
20 using System.Web.Security;
21 using System.Web.UI;
22 using System.Web.UI.WebControls;
23 using System.Web.DynamicData;
24 using System.Data.Objects.DataClasses;
25 using System.Collections.Specialized;
26 using System.ComponentModel;
27 using System.Collections.Generic;
28 using System.Windows.Forms;
29 using System.Security.Permissions;
30 using System.Drawing;
31 using System.Text;
32 using System.Globalization;
33 using System.Web.Configuration;
34     
35 [assembly:TagPrefix("System.Web.UI.WebControls", "asp")]
36 namespace System.Web.UI.WebControls
37 {
38     [
39     DefaultEvent("Selecting"),
40     DefaultProperty("EntitySetName"),
41     Designer("System.Web.UI.Design.WebControls.EntityDataSourceDesigner, " + AssemblyRef.SystemWebEntityDesign),
42     ParseChildren(true),
43     PersistChildren(false),
44     ResourceDescription(WebControlsRes.EntityDataSource_Description),
45     ResourceDisplayName(WebControlsRes.EntityDataSource_DisplayName),
46     ToolboxBitmap(typeof(EntityDataSource), "EntityDataSource.ico"),
47     ]
48     public class EntityDataSource : DataSourceControl, System.Web.DynamicData.IDynamicDataSource, IQueryableDataSource
49     {
50         #region Constants
51
52         private const int ORD_CONTROLSTATE = 0;
53         private const int ORD_VIEW = 1;
54         private const int ORD_WHERE_PARAMS = 2;
55         private const int ORD_COMMAND_PARAMS = 3;
56         private const int ORD_ORDERBY_PARAMS = 4;
57         private const int ORD_DELETE_PARAMS = 5;
58         private const int ORD_INSERT_PARAMS = 6;
59         private const int ORD_UPDATE_PARAMS = 7;
60         private const int ORD_SELECT_PARAMS = 8;
61
62         #endregion
63
64         #region Private Fields
65
66         private string _contextTypeName;
67         private string _entitySetName;
68         private string _defaultContainerName;
69         private string _where;
70         private string _orderBy;
71         private string _select;
72         private string _commandText;
73         private string _groupBy;
74         private string _include;
75         private string _entityTypeFilter;
76         private string _connectionString;
77
78         private ParameterCollection _commandParameters = null;
79         private ParameterCollection _whereParameters = null;
80         private ParameterCollection _orderByParameters = null;
81         private ParameterCollection _deleteParameters = null;
82         private ParameterCollection _updateParameters = null;
83         private ParameterCollection _insertParameters = null;
84         private ParameterCollection _selectParameters = null;
85
86         private string _viewName = "EntityDataSourceView";
87         private EntityDataSourceView _view = null;
88
89         private bool _enableUpdate = false;
90         private bool _enableDelete = false;
91         private bool _enableInsert = false;
92         private bool _autoSort = true;
93         private bool _autoPage = true;
94         private bool _autoGenerateWhereClause = false;
95         private bool _autoGenerateOrderByClause = false;
96         private bool _enableFlattening = true;
97         private bool _storeOriginalValuesInViewState = true;
98         private Type _contextType = null;
99
100         private readonly System.Data.EntityClient.EntityConnection _connection;
101         private readonly Version _targetFrameworkVersion;
102         #endregion
103
104         #region Public Surface
105
106         #region Constructors
107         public EntityDataSource()
108         {
109             _targetFrameworkVersion = HttpRuntime.TargetFramework;
110         }
111
112         public EntityDataSource(System.Data.EntityClient.EntityConnection connection)
113             : this()
114         {
115             _connection = connection;
116         }
117         #endregion
118
119         #region Public Properties
120
121         /// <summary>
122         /// Indicates whether the EntityDataSource is to automatically 
123         /// generate an OrderBy expression using property name(s) and value(s) from
124         /// the OrderByParameters.
125         /// </summary>
126         [
127         DefaultValue(false),
128         Category("Behavior"),
129         ResourceDescription(WebControlsRes.PropertyDescription_AutoGenerateOrderByClause)
130         ]
131         public bool AutoGenerateOrderByClause
132         {
133             get { return _autoGenerateOrderByClause; }
134             set
135             {
136                 _autoGenerateOrderByClause = value;
137                 View.RaiseChangedEvent();
138             }
139         }
140
141
142         /// <summary>
143         /// Indicates whether the EntityDataSource is to automatically 
144         /// generate a Where expression using property name(s) and value(s) from
145         /// the WhereParameters.
146         /// </summary>
147         [
148         DefaultValue(false),
149         Category("Behavior"),
150         ResourceDescription(WebControlsRes.PropertyDescription_AutoGenerateWhereClause)
151         ]
152         public bool AutoGenerateWhereClause
153         {
154             get { return _autoGenerateWhereClause; }
155             set
156             {
157                 _autoGenerateWhereClause = value;
158                 View.RaiseChangedEvent();
159             }
160         }
161
162         /// <summary>
163         /// Indicates to the EntityDataSource that the user wishes to perform paging.
164         /// </summary>
165         [
166         DefaultValue(true),
167         Category("Behavior"),
168         ResourceDescription(WebControlsRes.PropertyDescription_AutoPage)
169         ]
170         public bool AutoPage
171         {
172             get { return _autoPage; }
173             set
174             {
175                 _autoPage = value;
176                 View.RaiseChangedEvent();
177             }
178         }
179
180         /// <summary>
181         /// Indicates to the EntityDataSource that the user wishes to perform sorting.
182         /// </summary>
183         [
184         DefaultValue(true),
185         Category("Behavior"),
186         ResourceDescription(WebControlsRes.PropertyDescription_AutoSort)
187         ]
188         public bool AutoSort
189         {
190             get { return _autoSort; }
191             set
192             {
193                 _autoSort = value;
194                 View.RaiseChangedEvent();
195             }
196         }
197
198         /// <summary>
199         /// The name of the container. Required if DefaultConainerName is not set on the ObjectContext.
200         /// </summary>        
201         // devnote: Design-time attributes are not used here because this property is overridden by one in the designer
202         public string DefaultContainerName
203         {
204             get { return _defaultContainerName; }
205             set
206             {
207                 _defaultContainerName = value;
208                 View.RaiseChangedEvent();
209             }
210         }
211
212         internal System.Data.EntityClient.EntityConnection Connection
213         {
214             get { return _connection; }
215         }
216
217         /// <summary>
218         /// ConnectionString is required if DefaultContainerName is defined and neither
219         /// ContextType nor ContextTypeName are defined.
220         /// </summary>
221         public String ConnectionString
222         {
223             get { return _connectionString; }
224             set
225             {
226                 _connectionString = value;
227                 View.RaiseChangedEvent();
228             }
229         }
230
231         
232         
233         // devnote: Design-time attributes are not used here because this property is not visible in the designer (it is filtered out with PreFilterProperties)
234         /// <summary>
235         /// Defined by the IDynamicDataSource interface.
236         /// Provides a type to be used as the ObjectContext through which the EntityDataSource will 
237         /// provide operations to the EntityFramework
238         /// </summary>
239         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
240         public Type ContextType
241         {
242             get { return _contextType; }
243             set
244             {
245                 _contextType = value;
246                 if (null != value)
247                 {
248                     _contextTypeName = value.FullName;
249                 }
250                 else
251                 {
252                     _contextTypeName = null;
253                 }
254                 View.RaiseChangedEvent();
255             }
256         }
257
258         
259         /// <summary>
260         /// The fully-qualified type name for the ObjectContext through which the EntityDataSource will 
261         /// provide operations to the EntityFramework
262         /// </summary>
263         [
264         DefaultValue(null),
265         Category("Data"),
266         ResourceDescription(WebControlsRes.PropertyDescription_ContextTypeName)
267         ]
268         public string ContextTypeName
269         {
270             get { return _contextTypeName; }
271             set
272             {
273                 _contextTypeName = value;
274
275                 if (!String.IsNullOrEmpty(value) && System.Web.Hosting.HostingEnvironment.IsHosted)
276                 {
277                     _contextType = System.Web.Compilation.BuildManager.GetType(value, /*throwOnError*/false, /*ignoreCase*/true);
278                 }
279                 else
280                 {
281                     _contextType = null;
282                 }
283                 View.RaiseChangedEvent();
284             }
285         }
286
287         /// <summary>
288         /// Indicates to the EntityDataSource that the user wishes entities to be flattened or not.
289         /// </summary>
290         [
291         DefaultValue(true),
292         Category("Behavior"),
293         ResourceDescription(WebControlsRes.PropertyDescription_EnableFlattening)
294         ]
295         public bool EnableFlattening
296         {
297             get { return _enableFlattening; }
298             set
299             {
300                 _enableFlattening = value;
301                 View.RaiseChangedEvent();
302             }
303         }
304
305         /// <summary>
306         /// Provides default values for entities that are to be deleted.
307         /// Sets the named properties to the provided values only if the properties are null 
308         /// (not otherwise defined).
309         /// </summary>
310         [
311         DefaultValue(null),
312         MergableProperty(false),
313         PersistenceMode(PersistenceMode.InnerProperty),
314         Browsable(false)
315         ]
316         public ParameterCollection DeleteParameters
317         {
318             get
319             {
320                 if (null == _deleteParameters)
321                 {
322                     _deleteParameters = new ParameterCollection();
323                     if (UseNetFramework4Behavior)
324                     {
325                         _deleteParameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
326                     }
327                 }
328                 return _deleteParameters;
329             }
330         }
331
332         /// <summary>
333         /// Indicates to the EntityDataSource that the user wishes to perform delete operations.
334         /// </summary>
335         [
336         DefaultValue(false),
337         Category("Behavior"),
338         ResourceDescription(WebControlsRes.PropertyDescription_EnableDelete)
339         ]
340         public bool EnableDelete
341         {
342             get { return _enableDelete; }
343             set
344             {
345                 _enableDelete = value;
346                 View.RaiseChangedEvent();
347             }
348         }
349
350         /// <summary>
351         /// Indicates to the EntityDatSource that the user wishes to perform insert operations.
352         /// </summary>
353         [
354         DefaultValue(false),
355         Category("Behavior"),
356         ResourceDescription(WebControlsRes.PropertyDescription_EnableInsert)
357         ]
358         public bool EnableInsert
359         {
360             get { return _enableInsert; }
361             set
362             {
363                 _enableInsert = value;
364                 View.RaiseChangedEvent();
365             }
366         }
367
368         /// <summary>
369         /// Indicates to the EntityDataSource that the user wishes to perform update operations
370         /// </summary>
371         [
372         DefaultValue(false),
373         Category("Behavior"),
374         ResourceDescription(WebControlsRes.PropertyDescription_EnableUpdate)
375         ]
376         public bool EnableUpdate
377         {
378             get { return _enableUpdate; }
379             set
380             {
381                 _enableUpdate = value;
382                 View.RaiseChangedEvent();
383             }
384         }
385
386
387         /// <summary>
388         /// The name of the EntitySet used by this instance of the EntityDataSource control.
389         /// For editable scenarios, the EntitySetName is used as the EntitySql query expression.
390         /// All insert, update and delete operations are restricted to a single EntitySet.
391         /// </summary>
392         // devnote: Design-time attributes are not used here because this property is overridden by one in the designer
393         public string EntitySetName
394         {
395             get { return _entitySetName; }
396             set
397             {
398                 _entitySetName = value;
399                 View.RaiseChangedEvent();
400             }
401         }
402
403         /// <summary>
404         /// An arbitrary EntitySql CommandText for performing the query.
405         /// A query specified with CommandText is not editable.
406         /// </summary>
407         // devnote: Design-time attributes are not used here because this property is overridden by one in the designer
408         public string CommandText
409         {
410             get { return _commandText; }
411             set
412             {
413                 _commandText = value;
414                 View.RaiseChangedEvent();
415             }
416         }
417
418         /// <summary>
419         /// Named parameters to be used with the CommandText.
420         /// Corresponds to the ObjectParameters used in the ObjectQuery<T> query.
421         /// Null values are passed into the ObjectParameter collection as the Type of the Parameter.
422         /// </summary>
423         [
424         DefaultValue(null),
425         MergableProperty(false),
426         PersistenceMode(PersistenceMode.InnerProperty),
427         Browsable(false)
428         ]
429         public ParameterCollection CommandParameters
430         {
431             get
432             {
433                 if (null == _commandParameters)
434                 {
435                     _commandParameters = new ParameterCollection();
436                     _commandParameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
437                 }
438                 return _commandParameters;
439             }
440         }
441
442         internal string FQEntitySetName
443         {
444             get
445             {
446                 if (!String.IsNullOrEmpty(DefaultContainerName))
447                 {
448                     return DefaultContainerName + "." + EntitySetName;
449                 }
450                 return EntitySetName;
451             }
452         }
453
454         /// <summary>
455         /// The expression provided to the GroupBy ObjectQuery<T> builder method.
456         /// GroupBy expression requires Select to be defined.
457         /// These projections are not editable.
458         /// </summary>
459         [
460         Category("Data"),        
461         DefaultValue(null),
462         ResourceDescription(WebControlsRes.PropertyDescription_GroupBy),
463         ]        
464         public string GroupBy
465         {
466             get { return _groupBy; }
467             set
468             {
469                 _groupBy = value;
470                 View.RaiseChangedEvent();
471             }
472         }
473
474         /// <summary>
475         /// An expression approxaimately corresponding to the Include method on the ObjectQuery<T>.
476         /// Gets or sets an expression describing which navigations should be included in the query.
477         /// To describe a chain of navigations, use dots (e.g. "Orders.OrderDetails"). To include multiple
478         /// paths, use commas (e.g. "Orders.OrderDetails, Supplies").
479         /// </summary>
480         [
481         DefaultValue(null),
482         Category("Data"),
483         ResourceDescription(WebControlsRes.PropertyDescription_Include)
484         ]
485         public string Include
486         {
487             get
488             {
489                 return _include;
490             }
491             set
492             {
493                 _include = value;
494                 View.RaiseChangedEvent();
495             }
496         }
497
498
499         /// <summary>
500         /// Provides default values for inserted entities.
501         /// Properties that are null (not otherwise defined) are set to the value specified
502         /// by InsertParameters.
503         /// </summary>
504         [
505         DefaultValue(null),
506         MergableProperty(false),
507         PersistenceMode(PersistenceMode.InnerProperty),
508         Browsable(false)
509         ]
510         public ParameterCollection InsertParameters
511         {
512             get
513             {
514                 if (null == _insertParameters)
515                 {
516                     _insertParameters = new ParameterCollection();
517                     if (UseNetFramework4Behavior)
518                     {
519                         _insertParameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
520                     }
521                 }
522                 return _insertParameters;
523             }
524         }
525
526         // devnote: Design-time attributes are not used here because this property is overridden by one in the designer
527         
528         /// <summary>
529         /// Provides a sort expression corresonding to the OrderBy method on the ObjectQuery<T>
530         /// </summary>
531         public string OrderBy
532         {
533             get { return _orderBy; }
534             set
535             {
536                 _orderBy = value;
537                 View.RaiseChangedEvent();
538             }
539         }
540
541         /// <summary>
542         /// Each Parameter is mapped to as named ObjectParameter in the ObjectQuery<T>
543         /// If a null value is set on the Parameter, then the Type is passed in as the
544         /// ObjectParameter.
545         /// </summary>
546         [
547         DefaultValue(null),
548         MergableProperty(false),
549         PersistenceMode(PersistenceMode.InnerProperty),
550         Browsable(false)
551         ]
552         public ParameterCollection OrderByParameters
553         {
554             get
555             {
556                 if (null == _orderByParameters)
557                 {
558                     _orderByParameters = new ParameterCollection();
559                     _orderByParameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
560                 }
561                 return _orderByParameters;
562             }
563         }
564
565         // devnote: Design-time attributes are not used here because this property is overridden by one in the designer
566         /// <summary>
567         /// Forces the EntityDatSource to return entities of only a single derived type.
568         /// If the EntitySet provided as the query expression is polymorphic, then EntityTypeFilter
569         /// is required if the collection is to be editable.
570         /// </summary>
571         public string EntityTypeFilter
572         {
573             get { return _entityTypeFilter; }
574             set
575             {
576                 _entityTypeFilter = value;
577                 View.RaiseChangedEvent();
578             }
579         }
580
581         /// <summary>
582         /// Text for the Select query builder method.
583         /// Projections are not editable in the EntityDataSource control.
584         /// </summary>
585         // devnote: Design-time attributes are not used here because this property is overridden by one in the designer
586         public string Select
587         {
588             get  { return _select;  }
589             set
590             {
591                 _select = value;
592                 View.RaiseChangedEvent();
593             }
594         }
595         /// <summary>
596         /// Each Parameter is mapped to an ObjectParameter in the ObjectQuery<T>
597         /// If a null value is set on the Parameter, then the Type is passed in as the
598         /// named ObjectParameter.
599         /// </summary>
600         [
601         DefaultValue(null),
602         MergableProperty(false),
603         PersistenceMode(PersistenceMode.InnerProperty),
604         Browsable(false)
605         ]
606         public ParameterCollection SelectParameters
607         {
608             get
609             {
610                 if (null == _selectParameters)
611                 {
612                     _selectParameters = new ParameterCollection();
613                     _selectParameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
614                 }
615                 return _selectParameters;
616             }
617         }
618
619         /// <summary>
620         /// Setting this value to false disables storing original values in ViewState.
621         /// Setting this value to false implies that the user understands the concurrency model in the 
622         /// EntityFramework and the update behavior of the EntityDataSource. Its use should be 
623         /// reserved for expert users only.
624         /// </summary>
625         [
626         DefaultValue(true),
627         Category("Behavior"),
628         ResourceDescription(WebControlsRes.PropertyDescription_StoreOriginalValuesInViewState)
629         ]
630         public bool StoreOriginalValuesInViewState
631         {
632             get { return _storeOriginalValuesInViewState; }
633             set
634             {
635                 _storeOriginalValuesInViewState = value;
636                 View.RaiseChangedEvent();
637             }
638         }
639
640         /// <summary>
641         /// Provides default values to be used during updates. The values provided by UpdateParameters
642         /// are used for properties on the entity when the properties are null
643         /// </summary>
644         [
645         DefaultValue(null),
646         MergableProperty(false),
647         PersistenceMode(PersistenceMode.InnerProperty),
648         Browsable(false)
649         ]
650         public ParameterCollection UpdateParameters
651         {
652             get
653             {
654                 if (null == _updateParameters)
655                 {
656                     _updateParameters = new ParameterCollection();
657                     if (UseNetFramework4Behavior)
658                     {
659                         _updateParameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
660                     }
661                 }
662                 return _updateParameters;
663             }
664         }
665
666         /// <summary>
667         /// The text provided to the Where method on the ObjectQuery<T>
668         /// </summary>
669         // devnote: Design-time attributes are not used here because this property is overridden by one in the designer
670         public string Where
671         {
672             get { return _where;  }
673             set
674             {
675                 _where = value;
676                 View.RaiseChangedEvent();
677             }
678         }
679
680         /// <summary>
681         /// Each Parameter is mapped to an ObjectParameter in the ObjectQuery<T>
682         /// If a null value is set on the Parameter, then the Type is passed in as the
683         /// named ObjectParameter.
684         /// </summary>
685         [
686         DefaultValue(null),
687         MergableProperty(false),
688         PersistenceMode(PersistenceMode.InnerProperty),
689         Browsable(false)
690         ]
691         public ParameterCollection WhereParameters
692         {
693             get
694             {
695                 if (null == _whereParameters)
696                 {
697                     _whereParameters = new ParameterCollection();
698                     _whereParameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
699                 }
700                 return _whereParameters;
701             }
702         }
703
704         #endregion
705
706         #endregion
707
708         #region Property Getters
709
710         private ObjectParameter[] CreateObjectParametersFromParameterCollection(ParameterCollection paramColl)
711         {
712             IOrderedDictionary paramValues = paramColl.GetValues(HttpContext, this);
713
714             List<ObjectParameter>  objectParameters = new List<ObjectParameter>();
715             foreach (Parameter parameter in paramColl)
716             {
717                 if (!string.IsNullOrEmpty(parameter.Name))
718                 {
719                     WebControlParameterProxy wcParam = new WebControlParameterProxy(parameter, paramColl, this);
720
721                     if (wcParam.Value != null)
722                     {
723                         objectParameters.Add(new ObjectParameter(wcParam.Name, wcParam.Value));
724                     }
725                     else
726                     {
727                         objectParameters.Add(new ObjectParameter(wcParam.Name, wcParam.ClrType));
728                     }
729                 }
730             }
731             return objectParameters.ToArray();
732         }
733
734
735         internal ObjectParameter[] GetOrderByParameters()
736         {
737             return CreateObjectParametersFromParameterCollection(OrderByParameters);
738         }
739
740         internal ObjectParameter[] GetWhereParameters()
741         {
742             return CreateObjectParametersFromParameterCollection(WhereParameters);
743         }
744
745         // CommandParameters may be set in selectArgs
746         internal ObjectParameter[] GetCommandParameters()
747         {
748             return CreateObjectParametersFromParameterCollection(CommandParameters);
749         }
750
751         internal ObjectParameter[] GetSelectParameters()
752         {
753             return CreateObjectParametersFromParameterCollection(SelectParameters);
754         }
755
756         #endregion
757
758         #region DataSourceControl overrides
759         protected override DataSourceView GetView(string viewName)
760         {
761             return View;
762         }
763         protected override ICollection GetViewNames()
764         {
765             return new string[] { this._viewName };
766         }
767
768         #endregion
769
770         #region Private Properties
771         private EntityDataSourceView View
772         {
773             get
774             {
775                 if (null == _view)
776                 {
777                     _view = CreateView();
778                     if (IsTrackingViewState)
779                     {
780                         ((IStateManager)_view).TrackViewState();
781                     }
782                 }
783                 return _view;
784             }
785         }
786
787         /// <summary>
788         /// Users can override this method to control the creation of the data source view.
789         /// </summary>
790         /// <returns>An instance of EntityDataSourceView</returns>
791         protected virtual EntityDataSourceView CreateView()
792         {
793             return new EntityDataSourceView(this, _viewName);
794         }
795
796         internal HttpContext HttpContext
797         {
798             get
799             {
800                 return base.Context;
801             }
802         }
803
804         private bool UseNetFramework4Behavior
805         {
806             get
807             {
808                 return _targetFrameworkVersion == new Version(4, 0);
809             }
810         }
811
812         #endregion Private Properties
813
814         #region IStateManager overrides
815
816         protected override object SaveControlState()
817         {
818             // Order is sensitive, referenced by LoadControlState.
819             var state = new object[9];
820             state[ORD_CONTROLSTATE] = base.SaveControlState();
821             state[ORD_VIEW] = _view == null ? null : ((IStateManager)_view).SaveViewState();
822             state[ORD_WHERE_PARAMS] = SaveParametersViewState(_whereParameters);
823             state[ORD_COMMAND_PARAMS] = SaveParametersViewState(_commandParameters);
824             state[ORD_ORDERBY_PARAMS] = SaveParametersViewState(_orderByParameters);
825
826             if (UseNetFramework4Behavior)
827             {
828                 state[ORD_DELETE_PARAMS] = SaveParametersViewState(_deleteParameters);
829                 state[ORD_INSERT_PARAMS] = SaveParametersViewState(_insertParameters);
830                 state[ORD_UPDATE_PARAMS] = SaveParametersViewState(_updateParameters);
831             }
832
833             state[ORD_SELECT_PARAMS] = SaveParametersViewState(_selectParameters);
834             return state;
835         }
836
837         private object SaveParametersViewState(ParameterCollection parameters)
838         {
839             if (parameters != null) 
840             {
841                 return ((IStateManager)parameters).SaveViewState();
842             }
843             return null;
844         }
845
846         protected override void LoadControlState(object savedState)
847         {
848             if (null == savedState)
849             {
850                 base.LoadControlState(null);
851             }
852             else // (savedState != null)
853             {
854                 // Order is sensitive, referenced by SaveControlState.
855                 var state = (object[])savedState;
856                 if (state[ORD_CONTROLSTATE] != null)
857                 {
858                     base.LoadControlState(state[ORD_CONTROLSTATE]);
859                 }
860                 if (state[ORD_VIEW] != null)
861                 {
862                     ((IStateManager)View).LoadViewState(state[ORD_VIEW]);
863                 }
864                 if (state[ORD_WHERE_PARAMS] != null)
865                 {
866                     ((IStateManager)WhereParameters).LoadViewState(state[ORD_WHERE_PARAMS]);
867                 }
868                 if (state[ORD_COMMAND_PARAMS] != null)
869                 {
870                     ((IStateManager)CommandParameters).LoadViewState(state[ORD_COMMAND_PARAMS]);
871                 }
872                 if (state[ORD_ORDERBY_PARAMS] != null)
873                 {
874                     ((IStateManager)OrderByParameters).LoadViewState(state[ORD_ORDERBY_PARAMS]);
875                 }
876                 if (UseNetFramework4Behavior)
877                 {
878                     if (state[ORD_DELETE_PARAMS] != null)
879                     {
880                         ((IStateManager)DeleteParameters).LoadViewState(state[ORD_DELETE_PARAMS]);
881                     }
882                     if (state[ORD_INSERT_PARAMS] != null)
883                     {
884                         ((IStateManager)InsertParameters).LoadViewState(state[ORD_INSERT_PARAMS]);
885                     }
886                     if (state[ORD_UPDATE_PARAMS] != null)
887                     {
888                         ((IStateManager)UpdateParameters).LoadViewState(state[ORD_UPDATE_PARAMS]);
889                     }
890                 }
891                 if (state[ORD_SELECT_PARAMS] != null)
892                 {
893                     ((IStateManager)SelectParameters).LoadViewState(state[ORD_SELECT_PARAMS]);
894                 }
895             }
896         }
897
898         protected override void TrackViewState()
899         {
900             base.TrackViewState();
901             ((IStateManager)View).TrackViewState();
902             ((IStateManager)WhereParameters).TrackViewState();
903             ((IStateManager)CommandParameters).TrackViewState();
904             ((IStateManager)OrderByParameters).TrackViewState();
905             if (UseNetFramework4Behavior)
906             {
907                 ((IStateManager)DeleteParameters).TrackViewState();
908                 ((IStateManager)InsertParameters).TrackViewState();
909                 ((IStateManager)UpdateParameters).TrackViewState();
910             }
911             ((IStateManager)SelectParameters).TrackViewState();
912         }
913
914         #endregion
915
916         #region Events
917         event EventHandler<DynamicValidatorEventArgs> IDynamicDataSource.Exception
918         {
919             add { View.Exception += value; }
920             remove { View.Exception -= value; }
921         }
922
923         /// <summary>
924         /// An event that is fired just prior to the creation of the ObjectContext.
925         /// The user can provide their own context here.
926         /// </summary>
927         [
928         Category("Data"),
929         ResourceDescription(WebControlsRes.PropertyDescription_ContextCreating)
930         ]
931         public event EventHandler<EntityDataSourceContextCreatingEventArgs> ContextCreating
932         {
933             add { View.ContextCreating += value; }
934             remove { View.ContextCreating -= value; }
935         }
936
937         /// <summary>
938         /// An event that is fired just following the creation of the ObjectContext to provide
939         /// the user with a reference to the created context.
940         /// </summary>
941         [
942         Category("Data"),
943         ResourceDescription(WebControlsRes.PropertyDescription_ContextCreated)
944         ]
945         public event EventHandler<EntityDataSourceContextCreatedEventArgs> ContextCreated
946         {
947             add { View.ContextCreated += value; }
948             remove { View.ContextCreated -= value; }
949         }
950
951         /// <summary>
952         /// An event fired just prior to the ObjectContext being disposed.
953         /// It is cancellable in case the user needs to hold onto a reference to the Context.
954         /// </summary>
955         [
956         Category("Data"),
957         ResourceDescription(WebControlsRes.PropertyDescription_ContextDisposing)
958         ]
959         public event EventHandler<EntityDataSourceContextDisposingEventArgs> ContextDisposing
960         {
961             add { View.ContextDisposing += value; }
962             remove { View.ContextDisposing -= value; }
963         }
964
965         /// <summary>
966         /// An event fired prior to the execution of the query in the ExecuteSelect method. 
967         /// The user can modify the properties of the
968         /// EntityDataSource to modify its behavior.
969         /// The user can cancel the execution of the query in this event.
970         /// </summary>
971         [
972         Category("Data"),
973         ResourceDescription(WebControlsRes.PropertyDescription_Selecting)
974         ]
975         public event EventHandler<EntityDataSourceSelectingEventArgs> Selecting
976         {
977             add { View.Selecting += value; }
978             remove { View.Selecting -= value; }
979         }
980
981         /// <summary>
982         /// An event that is fired after the query has been executed in the ExecuteSelect method.
983         /// The event provides the collection of returned entities for inspection or modification prior to display.
984         /// </summary>
985         [
986         Category("Data"),
987         ResourceDescription(WebControlsRes.PropertyDescription_Selected)
988         ]
989         public event EventHandler<EntityDataSourceSelectedEventArgs> Selected
990         {
991             add { View.Selected += value; }
992             remove { View.Selected -= value; }
993         }
994
995         /// <summary>
996         /// An event fired just prior to deleting an object from the database.
997         /// The object is provided so the user can inspect or modify it.
998         /// The user can cancel the deletion.
999         /// </summary>
1000         [
1001         Category("Data"),
1002         ResourceDescription(WebControlsRes.PropertyDescription_Deleting)
1003         ]
1004         public event EventHandler<EntityDataSourceChangingEventArgs> Deleting
1005         {
1006             add { View.Deleting += value; }
1007             remove { View.Deleting -= value; }
1008         }
1009
1010         /// <summary>
1011         /// An event fired just after the entity has been deleted from the database.
1012         /// </summary>
1013         [
1014         Category("Data"),
1015         ResourceDescription(WebControlsRes.PropertyDescription_Deleted)
1016         ]
1017         public event EventHandler<EntityDataSourceChangedEventArgs> Deleted
1018         {
1019             add { View.Deleted += value; }
1020             remove { View.Deleted -= value; }
1021         }
1022
1023         /// <summary>
1024         /// An event fired just prior to the insertion of an entity into the database.
1025         /// The user is provided with the entity for modification prior to insertion.
1026         /// The insertion is cancellable.
1027         /// </summary>
1028         [
1029         Category("Data"),
1030         ResourceDescription(WebControlsRes.PropertyDescription_Inserting)
1031         ]
1032         public event EventHandler<EntityDataSourceChangingEventArgs> Inserting
1033         {
1034             add { View.Inserting += value; }
1035             remove { View.Inserting -= value; }
1036         }
1037
1038         /// <summary>
1039         /// An event fired just after the entity has been inserted into the database.
1040         /// </summary>
1041         [
1042         Category("Data"),
1043         ResourceDescription(WebControlsRes.PropertyDescription_Inserted)
1044         ]
1045         public event EventHandler<EntityDataSourceChangedEventArgs> Inserted
1046         {
1047             add { View.Inserted += value; }
1048             remove { View.Inserted -= value; }
1049         }
1050
1051         /// <summary>
1052         /// An event fired just after a modified entity has been updated in the database.
1053         /// </summary>
1054         [
1055         Category("Data"),
1056         ResourceDescription(WebControlsRes.PropertyDescription_Updated)
1057         ]
1058         public event EventHandler<EntityDataSourceChangedEventArgs> Updated
1059         {
1060             add { View.Updated += value; }
1061             remove { View.Updated -= value; }
1062         }
1063
1064         /// <summary>
1065         /// An event fired just prior to saving a modified entity to the database.
1066         /// The entity is provided to the event for modification.
1067         /// The update is cancellable.
1068         /// </summary>
1069         [
1070         Category("Data"),
1071         ResourceDescription(WebControlsRes.PropertyDescription_Updating)
1072         ]
1073         public event EventHandler<EntityDataSourceChangingEventArgs> Updating
1074         {
1075             add { View.Updating += value; }
1076             remove { View.Updating -= value; }
1077         }
1078
1079         #region IQueryableDataSource Members
1080
1081         [
1082         Category("Data"),
1083         ResourceDescription(WebControlsRes.PropertyDescription_QueryCreated)
1084         ]
1085         public event EventHandler<QueryCreatedEventArgs> QueryCreated
1086         {
1087             add { View.QueryCreated += value; }
1088             remove { View.QueryCreated -= value; }
1089         }
1090
1091         void IQueryableDataSource.RaiseViewChanged()
1092         {
1093             View.RaiseChangedEvent();
1094         }
1095
1096         #endregion
1097         
1098         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
1099         protected override void OnInit(EventArgs e)
1100         {
1101             base.OnInit(e);
1102             Debug.Assert(Page != null);
1103             Page.LoadComplete += new EventHandler(this.OnPageLoadComplete);
1104             if (StoreOriginalValuesInViewState && (View.CanDelete || View.CanUpdate))
1105             {
1106                 Page.RegisterRequiresViewStateEncryption();
1107             }
1108             Page.RegisterRequiresControlState(this);
1109         }
1110
1111         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
1112         protected override void OnUnload(EventArgs e)
1113         {
1114             base.OnUnload(e);
1115             if (null != _view) //Don't want to call View and create a new view during unload.
1116             {
1117                 _view.DisposeContext();
1118             }
1119         }
1120
1121         private void OnPageLoadComplete(object sender, EventArgs e)
1122         {
1123             CommandParameters.UpdateValues(HttpContext, this);
1124             WhereParameters.UpdateValues(HttpContext, this);
1125             OrderByParameters.UpdateValues(HttpContext, this);
1126             SelectParameters.UpdateValues(HttpContext, this);
1127         }
1128
1129         private void OnParametersChanged(object sender, EventArgs e)
1130         {
1131             View.RaiseChangedEvent();
1132         }
1133         #endregion
1134
1135         #region Error Checking
1136         internal bool ValidateUpdatableConditions()
1137         {
1138             bool anyEditablesEnabled = EnableInsert || EnableUpdate || EnableDelete;
1139
1140             // Cannot edit of EntitySetName has not been set.
1141             // Cannot edit if CommandText has been set.
1142             // Cannot edit if all EnableDelete/Insert/Update are false.
1143             // Cannot edit if Select has been set
1144             // Note that neither EntitySetName nor CommandText are strictly required if the user provides a query from OnSelecting.
1145             bool disableUpdatableness =
1146                 String.IsNullOrEmpty(EntitySetName) ||
1147                 !String.IsNullOrEmpty(CommandText) ||
1148                 !anyEditablesEnabled ||
1149                 !String.IsNullOrEmpty(Select) ||
1150                 !String.IsNullOrEmpty(GroupBy);
1151
1152             if (!String.IsNullOrEmpty(CommandText) &&
1153                 !String.IsNullOrEmpty(EntitySetName))
1154             {
1155                 throw new InvalidOperationException(Strings.EntityDataSource_CommandTextOrEntitySetName);
1156             }
1157
1158             if (String.IsNullOrEmpty(CommandText) && 
1159                 String.IsNullOrEmpty(EntitySetName))
1160             {
1161                 throw new InvalidOperationException(Strings.EntityDataSource_CommandTextOrEntitySetNameRequired);
1162             }
1163
1164             if (anyEditablesEnabled && !String.IsNullOrEmpty(CommandText))
1165             {
1166                 throw new InvalidOperationException(Strings.EntityDataSource_CommandTextNotEditable);
1167             }
1168
1169             if (anyEditablesEnabled && !String.IsNullOrEmpty(Select))
1170             {
1171                 throw new InvalidOperationException(Strings.EntityDataSource_SelectNotEditable);
1172             }
1173
1174             if (anyEditablesEnabled && !String.IsNullOrEmpty(GroupBy))
1175             {
1176                 throw new InvalidOperationException(Strings.EntityDataSource_GroupByNotEditable);
1177             }
1178
1179             if (!String.IsNullOrEmpty(Where) && AutoGenerateWhereClause)
1180             {
1181                 throw new InvalidOperationException(Strings.EntityDataSource_AutoGenerateWhereNotAllowedIfWhereDefined);
1182             }
1183
1184             if (!String.IsNullOrEmpty(OrderBy) && AutoGenerateOrderByClause)
1185             {
1186                 throw new InvalidOperationException(Strings.EntityDataSource_AutoGenerateOrderByNotAllowedIfOrderByIsDefined);
1187             }
1188
1189             if (0 < WhereParameters.Count && !AutoGenerateWhereClause && String.IsNullOrEmpty(Where))
1190             {
1191                 throw new InvalidOperationException(Strings.EntityDataSource_WhereParametersNeedsWhereOrAutoGenerateWhere);
1192             }
1193
1194             if (0 < OrderByParameters.Count && !AutoGenerateOrderByClause && String.IsNullOrEmpty(OrderBy))
1195             {
1196                 throw new InvalidOperationException(Strings.EntityDataSource_OrderByParametersNeedsOrderByOrAutoGenerateOrderBy);
1197             }
1198
1199             if (0 < CommandParameters.Count && String.IsNullOrEmpty(CommandText))
1200             {
1201                 throw new InvalidOperationException(Strings.EntityDataSource_CommandParametersNeedCommandText);
1202             }
1203
1204             if (0 < SelectParameters.Count && String.IsNullOrEmpty(Select))
1205             {
1206                 throw new InvalidOperationException(Strings.EntityDataSource_SelectParametersNeedSelect);
1207             }
1208
1209             if (!String.IsNullOrEmpty(GroupBy) && String.IsNullOrEmpty(Select))
1210             {
1211                 throw new InvalidOperationException(Strings.EntityDataSource_GroupByNeedsSelect);
1212             }
1213
1214             if (!String.IsNullOrEmpty(EntityTypeFilter) && !String.IsNullOrEmpty(CommandText))
1215             {
1216                 throw new InvalidOperationException(Strings.EntityDataSource_CommandTextCantHaveEntityTypeFilter);
1217             }
1218
1219             if (!String.IsNullOrEmpty(EntitySetName))
1220             {
1221                 View.ValidateEntitySetName();
1222             }
1223
1224             return disableUpdatableness;
1225         }
1226
1227         internal bool ValidateWrappable()
1228         {
1229             return
1230                 EnableFlattening &&
1231                 HasIdentity();
1232         }
1233
1234         /// <summary>
1235         /// Determines if the EntityDataSource is configured to return results that have an identity or not
1236         /// (i.e. the entities have some set of primary keys)
1237         /// </summary>
1238         internal bool HasIdentity()
1239         {
1240             return
1241                 String.IsNullOrEmpty(CommandText) &&
1242                 String.IsNullOrEmpty(Select) &&
1243                 String.IsNullOrEmpty(GroupBy);
1244         }
1245
1246         #endregion Error Checking
1247     }
1248 }