2 // LinqDataSourceView.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2008 Novell, Inc http://novell.com
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // FIXME: in general we should create something like
32 // System.Web.Query,Dynamic.DynamicClass to execute DataContext operations.
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.ComponentModel;
38 using System.Data.Linq;
39 using System.Reflection;
40 using System.Security.Permissions;
41 using System.Web.DynamicData;
44 namespace System.Web.UI.WebControls
46 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
47 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
48 public class LinqDataSourceView : DataSourceView, IStateManager
50 public LinqDataSourceView (LinqDataSource owner, string name, HttpContext context)
56 LinqDataSource source;
59 ParameterCollection delete_parameters,
61 select_new_parameters,
63 ParameterCollection group_by_parameters,
65 order_group_by_parameters,
68 IEnumerable<ParameterCollection> AllParameters {
70 yield return delete_parameters;
71 yield return insert_parameters;
72 yield return select_new_parameters;
73 yield return update_parameters;
74 yield return group_by_parameters;
75 yield return order_by_parameters;
76 yield return order_group_by_parameters;
77 yield return where_parameters;
82 public bool AutoGenerateOrderByClause { get; set; }
84 public bool AutoGenerateWhereClause { get; set; }
86 public bool AutoPage { get; set; }
88 public bool AutoSort { get; set; }
90 public override bool CanDelete {
91 get { return EnableDelete; }
94 public override bool CanInsert {
95 get { return EnableInsert; }
98 public override bool CanPage {
102 public override bool CanRetrieveTotalRowCount {
106 public override bool CanSort {
110 public override bool CanUpdate {
111 get { return EnableUpdate; }
114 protected virtual Type ContextType {
115 get { return ((IDynamicDataSource) source).ContextType; }
118 public virtual string ContextTypeName {
119 get { return source.ContextTypeName; }
120 set { source.ContextTypeName = value; }
124 public bool EnableDelete { get; set; }
126 public bool EnableInsert { get; set; }
128 public bool EnableObjectTracking { get; set; }
130 public bool EnableUpdate { get; set; }
133 public string TableName { get; set; }
136 public string GroupBy { get; set; }
139 public string OrderBy { get; set; }
142 public string OrderGroupsBy { get; set; }
145 public string SelectNew { get; set; }
148 public string Where { get; set; }
150 public ParameterCollection DeleteParameters {
151 get { return GetParameterCollection (ref delete_parameters, false, false); }
154 public ParameterCollection InsertParameters {
155 get { return GetParameterCollection (ref insert_parameters, false, false); }
158 public ParameterCollection UpdateParameters {
159 get { return GetParameterCollection (ref update_parameters, true, true); }
162 public ParameterCollection SelectNewParameters {
163 get { return GetParameterCollection (ref select_new_parameters, false, false); }
166 public ParameterCollection WhereParameters {
167 get { return GetParameterCollection (ref where_parameters, true, true); }
170 public ParameterCollection GroupByParameters {
171 get { return GetParameterCollection (ref group_by_parameters, true, true); }
174 public ParameterCollection OrderByParameters {
175 get { return GetParameterCollection (ref order_by_parameters, true, true); }
178 public ParameterCollection OrderGroupsByParameters {
179 get { return GetParameterCollection (ref order_group_by_parameters, true, true); }
182 ParameterCollection GetParameterCollection (ref ParameterCollection output, bool propagateTrackViewState, bool subscribeChanged)
187 output = new ParameterCollection ();
188 if (subscribeChanged)
189 output.ParametersChanged += new EventHandler (ParametersChanged);
191 if (IsTrackingViewState && propagateTrackViewState)
192 ((IStateManager) output).TrackViewState ();
197 void ParametersChanged (object source, EventArgs args)
199 OnDataSourceViewChanged (EventArgs.Empty);
204 object GetDataContext ()
206 if (data_context == null)
207 data_context = CreateContext (ContextType);
211 public int Delete (IDictionary keys, IDictionary oldValues)
213 return ExecuteDelete (keys, oldValues);
216 public int Insert (IDictionary values)
218 return ExecuteInsert (values);
221 public IEnumerable Select (DataSourceSelectArguments arguments)
223 return ExecuteSelect (arguments);
226 public int Update (IDictionary keys, IDictionary values, IDictionary oldValues)
228 return ExecuteUpdate (keys, values, oldValues);
232 protected override int ExecuteDelete (IDictionary keys, IDictionary oldValues)
234 throw new NotImplementedException ();
237 protected override int ExecuteInsert (IDictionary values)
239 var dc = (DataContext) GetDataContext ();
240 foreach (var mt in dc.Mapping.GetTables ()) {
241 if (mt.TableName != TableName)
244 var t = mt.RowType.Type;
245 ITable table = dc.GetTable (t);
246 object entity = Activator.CreateInstance (t);
247 // FIXME: merge InsertParameters
248 foreach (DictionaryEntry p in values)
249 t.GetProperty ((string) p.Key).SetValue (entity, p.Value, null);
251 InsertDataObject (dc, table, entity);
254 throw new InvalidOperationException (String.Format ("Table '{0}' was not found on the data context '{1}'", TableName, ContextType));
258 protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
260 throw new NotImplementedException ();
264 protected internal override IEnumerable ExecuteSelect (DataSourceSelectArguments arguments)
266 int max = arguments.MaximumRows;
267 max = max == 0 ? int.MaxValue : max;
268 int total = arguments.TotalRowCount;
269 total = total < 0 ? int.MaxValue : total;
270 int end = total == int.MaxValue ? total : arguments.StartRowIndex + total;
272 DataContext dc = Activator.CreateInstance (ContextType, true) as DataContext;
273 MemberInfo mi = GetTableMemberInfo (dc.GetType ());
275 // am totally not sure it is fine.
277 if (source.Select != null) {
278 // FIXME: merge SelectParameters.
279 results = dc.ExecuteQuery (mi is FieldInfo ? ((FieldInfo) mi).FieldType : ((PropertyInfo) mi).PropertyType, source.Select, new object [0]);
281 results = (IEnumerable) (mi is FieldInfo ? ((FieldInfo) mi).GetValue (dc) : ((PropertyInfo) mi).GetValue (dc, null));
285 foreach (var e in results) {
286 if (i++ < arguments.StartRowIndex)
287 continue; // skip rows before StartRowIndex.
293 protected virtual void DeleteDataObject (object dataContext, object table, object oldDataObject)
295 ITable itable = ((DataContext) dataContext).GetTable (table.GetType ());
296 itable.DeleteOnSubmit (oldDataObject);
299 protected virtual void InsertDataObject (object dataContext, object table, object newDataObject)
301 ITable itable = ((DataContext) dataContext).GetTable (table.GetType ());
302 itable.InsertOnSubmit (newDataObject);
306 protected virtual void ResetDataObject (object table, object dataObject)
308 var dc = GetDataContext ();
309 ITable itable = ((DataContext) dc).GetTable (table.GetType ());
310 UpdateDataObject (dc, table, dataObject, itable.GetOriginalEntityState (dataObject));
313 protected virtual void UpdateDataObject (object dataContext, object table, object oldDataObject, object newDataObject)
315 DeleteDataObject (dataContext, table, oldDataObject);
316 InsertDataObject (dataContext, table, newDataObject);
319 protected virtual object CreateContext (Type contextType)
321 OnContextCreating (new LinqDataSourceContextEventArgs ());
322 var o = Activator.CreateInstance (contextType);
323 OnContextCreated (new LinqDataSourceStatusEventArgs (o));
328 protected virtual Type GetDataObjectType (Type tableType)
330 throw new NotImplementedException ();
333 MemberInfo table_member;
335 protected virtual MemberInfo GetTableMemberInfo (Type contextType)
337 if (contextType == null)
338 throw new ArgumentNullException ("contextType");
339 if (String.IsNullOrEmpty (TableName))
340 throw new InvalidOperationException (String.Format ("The TableName property of LinqDataSource '{0}' must specify a table property or field on the data context type.", source.ID));
342 if (table_member != null && table_member.DeclaringType == contextType)
345 var marr = contextType.GetMember (TableName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty);
346 if (marr == null || marr.Length == 0)
347 throw new InvalidOperationException (String.Format ("Could not find a property or field called '{0}' on the data context type '{1}' of LinqDataSource '{2}'", TableName, contextType, source.ID));
349 table_member = marr [0];
356 protected virtual void ValidateContextType (Type contextType, bool selecting)
358 throw new NotImplementedException ();
361 protected virtual void ValidateDeleteSupported (IDictionary keys, IDictionary oldValues)
363 throw new NotImplementedException ();
366 protected virtual void ValidateInsertSupported (IDictionary values)
368 throw new NotImplementedException ();
371 protected virtual void ValidateOrderByParameter (string name, string value)
373 throw new NotImplementedException ();
376 protected virtual void ValidateParameterName (string name)
378 throw new NotImplementedException ();
381 protected virtual void ValidateTableType (Type tableType, bool selecting)
383 throw new NotImplementedException ();
386 protected virtual void ValidateUpdateSupported (IDictionary keys, IDictionary values, IDictionary oldValues)
388 throw new NotImplementedException ();
395 bool IStateManager.IsTrackingViewState {
396 get { return IsTrackingViewState; }
399 protected bool IsTrackingViewState {
400 get { return tracking; }
404 public bool StoreOriginalValuesInViewState {
405 get { throw new NotImplementedException (); }
406 set { throw new NotImplementedException (); }
409 void IStateManager.LoadViewState (object savedState)
411 LoadViewState (savedState);
414 object IStateManager.SaveViewState ()
416 return SaveViewState ();
419 void IStateManager.TrackViewState ()
424 protected virtual void LoadViewState (object savedState)
426 object [] vs = savedState as object [];
430 foreach (var p in AllParameters) {
432 ((IStateManager) p).LoadViewState (vs [i]);
437 protected virtual object SaveViewState ()
439 object [] vs = new object [8];
441 foreach (var p in AllParameters) {
443 vs [i] = ((IStateManager) p).SaveViewState ();
447 foreach (object o in vs)
453 protected virtual void TrackViewState ()
457 foreach (var p in AllParameters)
459 ((IStateManager) p).TrackViewState ();
464 #region Events and Overridable Event Handler Invocations
467 public event EventHandler<LinqDataSourceStatusEventArgs> ContextCreated;
469 public event EventHandler<LinqDataSourceContextEventArgs> ContextCreating;
471 public event EventHandler<LinqDataSourceDisposeEventArgs> ContextDisposing;
473 public event EventHandler<LinqDataSourceStatusEventArgs> Deleted;
475 public event EventHandler<LinqDataSourceDeleteEventArgs> Deleting;
477 internal event EventHandler<DynamicValidatorEventArgs> Exception;
479 public event EventHandler<LinqDataSourceStatusEventArgs> Inserted;
481 public event EventHandler<LinqDataSourceInsertEventArgs> Inserting;
483 public event EventHandler<LinqDataSourceStatusEventArgs> Selected;
485 public event EventHandler<LinqDataSourceSelectEventArgs> Selecting;
487 public event EventHandler<LinqDataSourceStatusEventArgs> Updated;
489 public event EventHandler<LinqDataSourceUpdateEventArgs> Updating;
491 protected virtual void OnContextCreated (LinqDataSourceStatusEventArgs e)
493 if (ContextCreated != null)
494 ContextCreated (this, e);
497 protected virtual void OnContextCreating (LinqDataSourceContextEventArgs e)
499 if (ContextCreating != null)
500 ContextCreating (this, e);
503 protected virtual void OnContextDisposing (LinqDataSourceDisposeEventArgs e)
505 if (ContextDisposing != null)
506 ContextDisposing (this, e);
509 protected virtual void OnDeleted (LinqDataSourceStatusEventArgs e)
515 protected virtual void OnDeleting (LinqDataSourceDeleteEventArgs e)
517 if (Deleting != null)
521 protected virtual void OnException (DynamicValidatorEventArgs e)
523 if (Exception != null)
527 protected virtual void OnInserted (LinqDataSourceStatusEventArgs e)
529 if (Inserted != null)
533 protected virtual void OnInserting (LinqDataSourceInsertEventArgs e)
535 if (Inserting != null)
539 protected virtual void OnSelected (LinqDataSourceStatusEventArgs e)
541 if (Selected != null)
545 protected virtual void OnSelecting (LinqDataSourceSelectEventArgs e)
547 if (Selecting != null)
551 protected virtual void OnUpdated (LinqDataSourceStatusEventArgs e)
557 protected virtual void OnUpdating (LinqDataSourceUpdateEventArgs e)
559 if (Updating != null)