3c1f479b9d
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
566 lines
16 KiB
C#
566 lines
16 KiB
C#
//
|
|
// LinqDataSourceView.cs
|
|
//
|
|
// Author:
|
|
// Atsushi Enomoto <atsushi@ximian.com>
|
|
//
|
|
// Copyright (C) 2008 Novell, Inc http://novell.com
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
// FIXME: in general we should create something like
|
|
// System.Web.Query,Dynamic.DynamicClass to execute DataContext operations.
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data.Linq;
|
|
using System.Reflection;
|
|
using System.Security.Permissions;
|
|
using System.Web.DynamicData;
|
|
using System.Web.UI;
|
|
|
|
namespace System.Web.UI.WebControls
|
|
{
|
|
[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|
[AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|
public class LinqDataSourceView : DataSourceView, IStateManager
|
|
{
|
|
public LinqDataSourceView (LinqDataSource owner, string name, HttpContext context)
|
|
: base (owner, name)
|
|
{
|
|
source = owner;
|
|
}
|
|
|
|
LinqDataSource source;
|
|
|
|
bool tracking;
|
|
ParameterCollection delete_parameters,
|
|
insert_parameters,
|
|
select_new_parameters,
|
|
update_parameters;
|
|
ParameterCollection group_by_parameters,
|
|
order_by_parameters,
|
|
order_group_by_parameters,
|
|
where_parameters;
|
|
|
|
IEnumerable<ParameterCollection> AllParameters {
|
|
get {
|
|
yield return delete_parameters;
|
|
yield return insert_parameters;
|
|
yield return select_new_parameters;
|
|
yield return update_parameters;
|
|
yield return group_by_parameters;
|
|
yield return order_by_parameters;
|
|
yield return order_group_by_parameters;
|
|
yield return where_parameters;
|
|
}
|
|
}
|
|
|
|
[MonoTODO]
|
|
public bool AutoGenerateOrderByClause { get; set; }
|
|
[MonoTODO]
|
|
public bool AutoGenerateWhereClause { get; set; }
|
|
[MonoTODO]
|
|
public bool AutoPage { get; set; }
|
|
[MonoTODO]
|
|
public bool AutoSort { get; set; }
|
|
|
|
public override bool CanDelete {
|
|
get { return EnableDelete; }
|
|
}
|
|
|
|
public override bool CanInsert {
|
|
get { return EnableInsert; }
|
|
}
|
|
|
|
public override bool CanPage {
|
|
get { return true; }
|
|
}
|
|
|
|
public override bool CanRetrieveTotalRowCount {
|
|
get { return true; }
|
|
}
|
|
|
|
public override bool CanSort {
|
|
get { return true; }
|
|
}
|
|
|
|
public override bool CanUpdate {
|
|
get { return EnableUpdate; }
|
|
}
|
|
|
|
protected virtual Type ContextType {
|
|
get { return ((IDynamicDataSource) source).ContextType; }
|
|
}
|
|
|
|
public virtual string ContextTypeName {
|
|
get { return source.ContextTypeName; }
|
|
set { source.ContextTypeName = value; }
|
|
}
|
|
|
|
[MonoTODO]
|
|
public bool EnableDelete { get; set; }
|
|
[MonoTODO]
|
|
public bool EnableInsert { get; set; }
|
|
[MonoTODO]
|
|
public bool EnableObjectTracking { get; set; }
|
|
[MonoTODO]
|
|
public bool EnableUpdate { get; set; }
|
|
|
|
[MonoTODO]
|
|
public string TableName { get; set; }
|
|
|
|
[MonoTODO]
|
|
public string GroupBy { get; set; }
|
|
|
|
[MonoTODO]
|
|
public string OrderBy { get; set; }
|
|
|
|
[MonoTODO]
|
|
public string OrderGroupsBy { get; set; }
|
|
|
|
[MonoTODO]
|
|
public string SelectNew { get; set; }
|
|
|
|
[MonoTODO]
|
|
public string Where { get; set; }
|
|
|
|
public ParameterCollection DeleteParameters {
|
|
get { return GetParameterCollection (ref delete_parameters, false, false); }
|
|
}
|
|
|
|
public ParameterCollection InsertParameters {
|
|
get { return GetParameterCollection (ref insert_parameters, false, false); }
|
|
}
|
|
|
|
public ParameterCollection UpdateParameters {
|
|
get { return GetParameterCollection (ref update_parameters, true, true); }
|
|
}
|
|
|
|
public ParameterCollection SelectNewParameters {
|
|
get { return GetParameterCollection (ref select_new_parameters, false, false); }
|
|
}
|
|
|
|
public ParameterCollection WhereParameters {
|
|
get { return GetParameterCollection (ref where_parameters, true, true); }
|
|
}
|
|
|
|
public ParameterCollection GroupByParameters {
|
|
get { return GetParameterCollection (ref group_by_parameters, true, true); }
|
|
}
|
|
|
|
public ParameterCollection OrderByParameters {
|
|
get { return GetParameterCollection (ref order_by_parameters, true, true); }
|
|
}
|
|
|
|
public ParameterCollection OrderGroupsByParameters {
|
|
get { return GetParameterCollection (ref order_group_by_parameters, true, true); }
|
|
}
|
|
|
|
ParameterCollection GetParameterCollection (ref ParameterCollection output, bool propagateTrackViewState, bool subscribeChanged)
|
|
{
|
|
if (output != null)
|
|
return output;
|
|
|
|
output = new ParameterCollection ();
|
|
if (subscribeChanged)
|
|
output.ParametersChanged += new EventHandler (ParametersChanged);
|
|
|
|
if (IsTrackingViewState && propagateTrackViewState)
|
|
((IStateManager) output).TrackViewState ();
|
|
|
|
return output;
|
|
}
|
|
|
|
void ParametersChanged (object source, EventArgs args)
|
|
{
|
|
OnDataSourceViewChanged (EventArgs.Empty);
|
|
}
|
|
|
|
object data_context;
|
|
|
|
object GetDataContext ()
|
|
{
|
|
if (data_context == null)
|
|
data_context = CreateContext (ContextType);
|
|
return data_context;
|
|
}
|
|
|
|
public int Delete (IDictionary keys, IDictionary oldValues)
|
|
{
|
|
return ExecuteDelete (keys, oldValues);
|
|
}
|
|
|
|
public int Insert (IDictionary values)
|
|
{
|
|
return ExecuteInsert (values);
|
|
}
|
|
|
|
public IEnumerable Select (DataSourceSelectArguments arguments)
|
|
{
|
|
return ExecuteSelect (arguments);
|
|
}
|
|
|
|
public int Update (IDictionary keys, IDictionary values, IDictionary oldValues)
|
|
{
|
|
return ExecuteUpdate (keys, values, oldValues);
|
|
}
|
|
|
|
[MonoTODO]
|
|
protected override int ExecuteDelete (IDictionary keys, IDictionary oldValues)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
protected override int ExecuteInsert (IDictionary values)
|
|
{
|
|
var dc = (DataContext) GetDataContext ();
|
|
foreach (var mt in dc.Mapping.GetTables ()) {
|
|
if (mt.TableName != TableName)
|
|
continue;
|
|
|
|
var t = mt.RowType.Type;
|
|
ITable table = dc.GetTable (t);
|
|
object entity = Activator.CreateInstance (t);
|
|
// FIXME: merge InsertParameters
|
|
foreach (DictionaryEntry p in values)
|
|
t.GetProperty ((string) p.Key).SetValue (entity, p.Value, null);
|
|
|
|
InsertDataObject (dc, table, entity);
|
|
return 1;
|
|
}
|
|
throw new InvalidOperationException (String.Format ("Table '{0}' was not found on the data context '{1}'", TableName, ContextType));
|
|
}
|
|
|
|
[MonoTODO]
|
|
protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO]
|
|
protected internal override IEnumerable ExecuteSelect (DataSourceSelectArguments arguments)
|
|
{
|
|
int max = arguments.MaximumRows;
|
|
max = max == 0 ? int.MaxValue : max;
|
|
int total = arguments.TotalRowCount;
|
|
total = total < 0 ? int.MaxValue : total;
|
|
int end = total == int.MaxValue ? total : arguments.StartRowIndex + total;
|
|
|
|
DataContext dc = Activator.CreateInstance (ContextType, true) as DataContext;
|
|
MemberInfo mi = GetTableMemberInfo (dc.GetType ());
|
|
|
|
// am totally not sure it is fine.
|
|
IEnumerable results;
|
|
if (source.Select != null) {
|
|
// FIXME: merge SelectParameters.
|
|
results = dc.ExecuteQuery (mi is FieldInfo ? ((FieldInfo) mi).FieldType : ((PropertyInfo) mi).PropertyType, source.Select, new object [0]);
|
|
} else {
|
|
results = (IEnumerable) (mi is FieldInfo ? ((FieldInfo) mi).GetValue (dc) : ((PropertyInfo) mi).GetValue (dc, null));
|
|
}
|
|
|
|
int i = 0;
|
|
foreach (var e in results) {
|
|
if (i++ < arguments.StartRowIndex)
|
|
continue; // skip rows before StartRowIndex.
|
|
if (i < end)
|
|
yield return e;
|
|
}
|
|
}
|
|
|
|
protected virtual void DeleteDataObject (object dataContext, object table, object oldDataObject)
|
|
{
|
|
ITable itable = ((DataContext) dataContext).GetTable (table.GetType ());
|
|
itable.DeleteOnSubmit (oldDataObject);
|
|
}
|
|
|
|
protected virtual void InsertDataObject (object dataContext, object table, object newDataObject)
|
|
{
|
|
ITable itable = ((DataContext) dataContext).GetTable (table.GetType ());
|
|
itable.InsertOnSubmit (newDataObject);
|
|
}
|
|
|
|
[MonoTODO]
|
|
protected virtual void ResetDataObject (object table, object dataObject)
|
|
{
|
|
var dc = GetDataContext ();
|
|
ITable itable = ((DataContext) dc).GetTable (table.GetType ());
|
|
UpdateDataObject (dc, table, dataObject, itable.GetOriginalEntityState (dataObject));
|
|
}
|
|
|
|
protected virtual void UpdateDataObject (object dataContext, object table, object oldDataObject, object newDataObject)
|
|
{
|
|
DeleteDataObject (dataContext, table, oldDataObject);
|
|
InsertDataObject (dataContext, table, newDataObject);
|
|
}
|
|
|
|
protected virtual object CreateContext (Type contextType)
|
|
{
|
|
OnContextCreating (new LinqDataSourceContextEventArgs ());
|
|
var o = Activator.CreateInstance (contextType);
|
|
OnContextCreated (new LinqDataSourceStatusEventArgs (o));
|
|
return o;
|
|
}
|
|
|
|
[MonoTODO]
|
|
protected virtual Type GetDataObjectType (Type tableType)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
MemberInfo table_member;
|
|
|
|
protected virtual MemberInfo GetTableMemberInfo (Type contextType)
|
|
{
|
|
if (contextType == null)
|
|
throw new ArgumentNullException ("contextType");
|
|
if (String.IsNullOrEmpty (TableName))
|
|
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));
|
|
|
|
if (table_member != null && table_member.DeclaringType == contextType)
|
|
return table_member;
|
|
|
|
var marr = contextType.GetMember (TableName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty);
|
|
if (marr == null || marr.Length == 0)
|
|
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));
|
|
|
|
table_member = marr [0];
|
|
return table_member;
|
|
}
|
|
|
|
#region Validation
|
|
|
|
[MonoTODO]
|
|
protected virtual void ValidateContextType (Type contextType, bool selecting)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
[MonoTODO]
|
|
protected virtual void ValidateDeleteSupported (IDictionary keys, IDictionary oldValues)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
[MonoTODO]
|
|
protected virtual void ValidateInsertSupported (IDictionary values)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
[MonoTODO]
|
|
protected virtual void ValidateOrderByParameter (string name, string value)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
[MonoTODO]
|
|
protected virtual void ValidateParameterName (string name)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
[MonoTODO]
|
|
protected virtual void ValidateTableType (Type tableType, bool selecting)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
[MonoTODO]
|
|
protected virtual void ValidateUpdateSupported (IDictionary keys, IDictionary values, IDictionary oldValues)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ViewState
|
|
|
|
bool IStateManager.IsTrackingViewState {
|
|
get { return IsTrackingViewState; }
|
|
}
|
|
|
|
protected bool IsTrackingViewState {
|
|
get { return tracking; }
|
|
}
|
|
|
|
[MonoTODO]
|
|
public bool StoreOriginalValuesInViewState {
|
|
get { throw new NotImplementedException (); }
|
|
set { throw new NotImplementedException (); }
|
|
}
|
|
|
|
void IStateManager.LoadViewState (object savedState)
|
|
{
|
|
LoadViewState (savedState);
|
|
}
|
|
|
|
object IStateManager.SaveViewState ()
|
|
{
|
|
return SaveViewState ();
|
|
}
|
|
|
|
void IStateManager.TrackViewState ()
|
|
{
|
|
TrackViewState ();
|
|
}
|
|
|
|
protected virtual void LoadViewState (object savedState)
|
|
{
|
|
object [] vs = savedState as object [];
|
|
if (vs == null)
|
|
return;
|
|
int i = 0;
|
|
foreach (var p in AllParameters) {
|
|
if (vs [i] != null)
|
|
((IStateManager) p).LoadViewState (vs [i]);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
protected virtual object SaveViewState ()
|
|
{
|
|
object [] vs = new object [8];
|
|
int i = 0;
|
|
foreach (var p in AllParameters) {
|
|
if (p != null)
|
|
vs [i] = ((IStateManager) p).SaveViewState ();
|
|
i++;
|
|
}
|
|
|
|
foreach (object o in vs)
|
|
if (o != null)
|
|
return vs;
|
|
return null;
|
|
}
|
|
|
|
protected virtual void TrackViewState ()
|
|
{
|
|
tracking = true;
|
|
|
|
foreach (var p in AllParameters)
|
|
if (p != null)
|
|
((IStateManager) p).TrackViewState ();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Events and Overridable Event Handler Invocations
|
|
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceStatusEventArgs> ContextCreated;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceContextEventArgs> ContextCreating;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceDisposeEventArgs> ContextDisposing;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceStatusEventArgs> Deleted;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceDeleteEventArgs> Deleting;
|
|
[MonoTODO]
|
|
internal event EventHandler<DynamicValidatorEventArgs> Exception;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceStatusEventArgs> Inserted;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceInsertEventArgs> Inserting;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceStatusEventArgs> Selected;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceSelectEventArgs> Selecting;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceStatusEventArgs> Updated;
|
|
[MonoTODO]
|
|
public event EventHandler<LinqDataSourceUpdateEventArgs> Updating;
|
|
|
|
protected virtual void OnContextCreated (LinqDataSourceStatusEventArgs e)
|
|
{
|
|
if (ContextCreated != null)
|
|
ContextCreated (this, e);
|
|
}
|
|
|
|
protected virtual void OnContextCreating (LinqDataSourceContextEventArgs e)
|
|
{
|
|
if (ContextCreating != null)
|
|
ContextCreating (this, e);
|
|
}
|
|
|
|
protected virtual void OnContextDisposing (LinqDataSourceDisposeEventArgs e)
|
|
{
|
|
if (ContextDisposing != null)
|
|
ContextDisposing (this, e);
|
|
}
|
|
|
|
protected virtual void OnDeleted (LinqDataSourceStatusEventArgs e)
|
|
{
|
|
if (Deleted != null)
|
|
Deleted (this, e);
|
|
}
|
|
|
|
protected virtual void OnDeleting (LinqDataSourceDeleteEventArgs e)
|
|
{
|
|
if (Deleting != null)
|
|
Deleting (this, e);
|
|
}
|
|
|
|
protected virtual void OnException (DynamicValidatorEventArgs e)
|
|
{
|
|
if (Exception != null)
|
|
Exception (this, e);
|
|
}
|
|
|
|
protected virtual void OnInserted (LinqDataSourceStatusEventArgs e)
|
|
{
|
|
if (Inserted != null)
|
|
Inserted (this, e);
|
|
}
|
|
|
|
protected virtual void OnInserting (LinqDataSourceInsertEventArgs e)
|
|
{
|
|
if (Inserting != null)
|
|
Inserting (this, e);
|
|
}
|
|
|
|
protected virtual void OnSelected (LinqDataSourceStatusEventArgs e)
|
|
{
|
|
if (Selected != null)
|
|
Selected (this, e);
|
|
}
|
|
|
|
protected virtual void OnSelecting (LinqDataSourceSelectEventArgs e)
|
|
{
|
|
if (Selecting != null)
|
|
Selecting (this, e);
|
|
}
|
|
|
|
protected virtual void OnUpdated (LinqDataSourceStatusEventArgs e)
|
|
{
|
|
if (Updated != null)
|
|
Updated (this, e);
|
|
}
|
|
|
|
protected virtual void OnUpdating (LinqDataSourceUpdateEventArgs e)
|
|
{
|
|
if (Updating != null)
|
|
Updating (this, e);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|