|
//------------------------------------------------------------------------------
// <copyright file="LinqDataSourceView.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.UI.WebControls {
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Compilation;
using System.Web.Query.Dynamic;
using System.Web.Resources;
using System.Security;
using System.Security.Permissions;
using DynamicValidatorEventArgs = System.Web.DynamicData.DynamicValidatorEventArgs;
using DynamicDataSourceOperation = System.Web.DynamicData.DynamicDataSourceOperation;
public partial class LinqDataSourceView : ContextDataSourceView {
private static readonly object EventDeleted = new object();
private static readonly object EventDeleting = new object();
private static readonly object EventException = new object();
private static readonly object EventInserted = new object();
private static readonly object EventInserting = new object();
private static readonly object EventUpdated = new object();
private static readonly object EventUpdating = new object();
private HttpContext _context;
private Type _contextType;
private string _contextTypeName;
private LinqDataSource _owner;
private List<ContextDataSourceContextData> _selectContexts;
private bool _enableDelete;
private bool _enableInsert;
private bool _enableObjectTracking = true;
private bool _enableUpdate;
private bool _isNewContext;
private ILinqToSql _linqToSql;
private bool _reuseSelectContext;
private bool _storeOriginalValuesInViewState = true;
private bool _storeOriginalValues;
private object _selectResult;
public LinqDataSourceView(LinqDataSource owner, string name, HttpContext context)
: this(owner, name, context, new DynamicQueryableWrapper(), new LinqToSqlWrapper()) {
}
// internal constructor that takes mocks for unit tests.
internal LinqDataSourceView(LinqDataSource owner, string name, HttpContext context,
IDynamicQueryable dynamicQueryable, ILinqToSql linqToSql)
: base(owner, name, context, dynamicQueryable) {
_context = context;
_owner = owner;
_linqToSql = linqToSql;
}
public override bool CanDelete {
get {
return EnableDelete;
}
}
public override bool CanInsert {
get {
return EnableInsert;
}
}
// When AutoPage is false the user should manually page in the Selecting event.
public override bool CanPage {
get {
return true;
}
}
// When AutoPage is false the user must set the total row count in the Selecting event.
public override bool CanRetrieveTotalRowCount {
get {
return true;
}
}
// When AutoSort is false the user should manually sort in the Selecting event.
public override bool CanSort {
get {
return true;
}
}
public override bool CanUpdate {
get {
return EnableUpdate;
}
}
public override Type ContextType {
[SecuritySafeCritical]
get {
if (_contextType == null) {
string typeName = ContextTypeName;
if (String.IsNullOrEmpty(typeName)) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_ContextTypeNameNotSpecified, _owner.ID));
}
try {
_contextType = BuildManager.GetType(typeName, /*throwOnFail*/true, /*ignoreCase*/true);
}
catch (Exception e) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_ContextTypeNameNotFound, _owner.ID), e);
}
}
return _contextType;
}
}
public override string ContextTypeName {
get {
return _contextTypeName ?? String.Empty;
}
set {
if (_contextTypeName != value) {
if (_reuseSelectContext) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_ContextTypeNameChanged, _owner.ID));
}
_contextTypeName = value;
_contextType = null;
OnDataSourceViewChanged(EventArgs.Empty);
}
}
}
public bool EnableDelete {
get {
return _enableDelete;
}
set {
if (_enableDelete != value) {
_enableDelete = value;
OnDataSourceViewChanged(EventArgs.Empty);
}
}
}
public bool EnableInsert {
get {
return _enableInsert;
}
set {
if (_enableInsert != value) {
_enableInsert = value;
OnDataSourceViewChanged(EventArgs.Empty);
}
}
}
public bool EnableObjectTracking {
get {
return _enableObjectTracking;
}
set {
if (_enableObjectTracking != value) {
if (_reuseSelectContext) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_EnableObjectTrackingChanged, _owner.ID));
}
_enableObjectTracking = value;
}
}
}
public bool EnableUpdate {
get {
return _enableUpdate;
}
set {
if (_enableUpdate != value) {
_enableUpdate = value;
OnDataSourceViewChanged(EventArgs.Empty);
}
}
}
public bool StoreOriginalValuesInViewState {
get {
return _storeOriginalValuesInViewState;
}
set {
if (_storeOriginalValuesInViewState != value) {
_storeOriginalValuesInViewState = value;
OnDataSourceViewChanged(EventArgs.Empty);
}
}
}
public string TableName {
get {
return EntitySetName;
}
set {
if (EntitySetName != value) {
if (_reuseSelectContext) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_TableNameChanged, _owner.ID));
}
EntitySetName = value;
}
}
}
public event EventHandler<LinqDataSourceStatusEventArgs> ContextCreated {
add {
Events.AddHandler(EventContextCreated, value);
}
remove {
Events.RemoveHandler(EventContextCreated, value);
}
}
public event EventHandler<LinqDataSourceContextEventArgs> ContextCreating {
add {
Events.AddHandler(EventContextCreating, value);
}
remove {
Events.RemoveHandler(EventContextCreating, value);
}
}
public event EventHandler<LinqDataSourceDisposeEventArgs> ContextDisposing {
add {
Events.AddHandler(EventContextDisposing, value);
}
remove {
Events.RemoveHandler(EventContextDisposing, value);
}
}
public event EventHandler<LinqDataSourceStatusEventArgs> Deleted {
add {
Events.AddHandler(EventDeleted, value);
}
remove {
Events.RemoveHandler(EventDeleted, value);
}
}
public event EventHandler<LinqDataSourceDeleteEventArgs> Deleting {
add {
Events.AddHandler(EventDeleting, value);
}
remove {
Events.RemoveHandler(EventDeleting, value);
}
}
internal event EventHandler<DynamicValidatorEventArgs> Exception {
add {
Events.AddHandler(EventException, value);
}
remove {
Events.RemoveHandler(EventException, value);
}
}
public event EventHandler<LinqDataSourceStatusEventArgs> Inserted {
add {
Events.AddHandler(EventInserted, value);
}
remove {
Events.RemoveHandler(EventInserted, value);
}
}
public event EventHandler<LinqDataSourceInsertEventArgs> Inserting {
add {
Events.AddHandler(EventInserting, value);
}
remove {
Events.RemoveHandler(EventInserting, value);
}
}
public event EventHandler<LinqDataSourceStatusEventArgs> Selected {
add {
Events.AddHandler(EventSelected, value);
}
remove {
Events.RemoveHandler(EventSelected, value);
}
}
public event EventHandler<LinqDataSourceSelectEventArgs> Selecting {
add {
Events.AddHandler(EventSelecting, value);
}
remove {
Events.RemoveHandler(EventSelecting, value);
}
}
public event EventHandler<LinqDataSourceStatusEventArgs> Updated {
add {
Events.AddHandler(EventUpdated, value);
}
remove {
Events.RemoveHandler(EventUpdated, value);
}
}
public event EventHandler<LinqDataSourceUpdateEventArgs> Updating {
add {
Events.AddHandler(EventUpdating, value);
}
remove {
Events.RemoveHandler(EventUpdating, value);
}
}
protected virtual object CreateContext(Type contextType) {
return DataSourceHelper.CreateObjectInstance(contextType);
}
protected override ContextDataSourceContextData CreateContext(DataSourceOperation operation) {
if (operation == DataSourceOperation.Select) {
return CreateContextAndTableForSelect();
}
return CreateContextAndTableForEdit(operation);
}
private ContextDataSourceContextData CreateContextAndTable(DataSourceOperation operation) {
ContextDataSourceContextData contextData = null;
bool eventFired = false;
try {
LinqDataSourceContextEventArgs contextEventArgs = new LinqDataSourceContextEventArgs(operation);
OnContextCreating(contextEventArgs);
contextData = new ContextDataSourceContextData(contextEventArgs.ObjectInstance);
Type contextType = null;
MemberInfo tableMemberInfo = null;
if (contextData.Context == null) {
// construct the context unless accessing a static table for Select.
contextType = ContextType;
tableMemberInfo = GetTableMemberInfo(contextType);
if (tableMemberInfo != null) {
if (MemberIsStatic(tableMemberInfo)) {
if (operation != DataSourceOperation.Select) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_TableCannotBeStatic, TableName, contextType.Name, _owner.ID));
}
}
else {
contextData.Context = CreateContext(contextType);
_isNewContext = true;
}
}
}
else {
// use the manually constructed context.
tableMemberInfo = GetTableMemberInfo(contextData.Context.GetType());
}
// fetch the table from the context.
if (tableMemberInfo != null) {
FieldInfo field = tableMemberInfo as FieldInfo;
if (field != null) {
contextData.EntitySet = field.GetValue(contextData.Context);
}
PropertyInfo property = tableMemberInfo as PropertyInfo;
if (property != null) {
contextData.EntitySet = property.GetValue(contextData.Context, null);
}
}
if (contextData.EntitySet == null) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_TableNameNotFound, TableName, contextType.Name, _owner.ID));
}
}
catch (Exception e) {
eventFired = true;
LinqDataSourceStatusEventArgs createdEventArgs = new LinqDataSourceStatusEventArgs(e);
OnContextCreated(createdEventArgs);
OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.ContextCreate));
// CreateContextAndTable will return null if this exception is handled.
if (!createdEventArgs.ExceptionHandled) {
throw;
}
}
finally {
if (!eventFired) {
// contextData can be null if exception thrown from ContextCreating handler.
object context = (contextData == null) ? null : contextData.Context;
LinqDataSourceStatusEventArgs createdEventArgs = new LinqDataSourceStatusEventArgs(context);
OnContextCreated(createdEventArgs);
}
}
return contextData;
}
private ContextDataSourceContextData CreateContextAndTableForEdit(DataSourceOperation operation) {
ContextDataSourceContextData contextData = CreateContextAndTable(operation);
// context data may be null or incomplete if an exception was handled
if (contextData != null) {
if (contextData.Context == null) {
return null;
}
if (contextData.EntitySet == null) {
DisposeContext(contextData.Context);
return null;
}
ValidateContextType(contextData.Context.GetType(), false);
ValidateTableType(contextData.EntitySet.GetType(), false);
}
return contextData;
}
private ContextDataSourceContextData CreateContextAndTableForSelect() {
_isNewContext = false;
if (_selectContexts == null) {
_selectContexts = new List<ContextDataSourceContextData>();
}
else if (_reuseSelectContext && _selectContexts.Count > 0) {
return _selectContexts[_selectContexts.Count - 1];
}
// context data may be null if an exception was handled
ContextDataSourceContextData contextData = CreateContextAndTable(DataSourceOperation.Select);
if (contextData != null) {
if (contextData.Context != null) {
ValidateContextType(contextData.Context.GetType(), true);
}
if (contextData.EntitySet != null) {
ValidateTableType(contextData.EntitySet.GetType(), true);
}
_selectContexts.Add(contextData);
// context may not be dlinq context or may be null if table was static.
DataContext dlinqContext = contextData.Context as DataContext;
if ((dlinqContext != null) && _isNewContext) {
dlinqContext.ObjectTrackingEnabled = EnableObjectTracking;
}
// don't reuse dlinq contexts that cache data or exterior changes will not be reflected.
_reuseSelectContext = (dlinqContext == null) || !EnableObjectTracking;
}
return contextData;
}
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object",
Justification = "Names are consistent with those used in the ObjectDataSource classes")]
protected virtual void DeleteDataObject(object dataContext, object table, object oldDataObject) {
_linqToSql.Attach((ITable)table, oldDataObject);
_linqToSql.Remove((ITable)table, oldDataObject);
_linqToSql.SubmitChanges((DataContext)dataContext);
}
protected override int DeleteObject(object oldEntity) {
LinqDataSourceDeleteEventArgs deleteEventArgs = new LinqDataSourceDeleteEventArgs(oldEntity);
OnDeleting(deleteEventArgs);
if (deleteEventArgs.Cancel) {
return -1;
}
LinqDataSourceStatusEventArgs deletedEventArgs = null;
try {
DeleteDataObject(Context, EntitySet, deleteEventArgs.OriginalObject);
}
catch (Exception e) {
// allow user to handle dlinq exceptions including OnValidate validation.
deletedEventArgs = new LinqDataSourceStatusEventArgs(e);
OnDeleted(deletedEventArgs);
OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Delete));
if (deletedEventArgs.ExceptionHandled) {
return -1;
}
throw;
}
deletedEventArgs = new LinqDataSourceStatusEventArgs(deleteEventArgs.OriginalObject);
OnDeleted(deletedEventArgs);
return 1;
}
protected override void DisposeContext(object dataContext) {
if (dataContext != null) {
LinqDataSourceDisposeEventArgs disposingEventArgs = new LinqDataSourceDisposeEventArgs(dataContext);
OnContextDisposing(disposingEventArgs);
if (!disposingEventArgs.Cancel) {
base.DisposeContext(dataContext);
}
}
}
protected override int ExecuteDelete(IDictionary keys, IDictionary oldValues) {
ValidateDeleteSupported(keys, oldValues);
return base.ExecuteDelete(keys, oldValues);
}
protected override int ExecuteInsert(IDictionary values) {
ValidateInsertSupported(values);
return base.ExecuteInsert(values);
}
protected override int ExecuteUpdate(IDictionary keys, IDictionary values, IDictionary oldValues) {
ValidateUpdateSupported(keys, values, oldValues);
return base.ExecuteUpdate(keys, values, oldValues);
}
protected internal override IEnumerable ExecuteSelect(DataSourceSelectArguments arguments) {
ClearOriginalValues();
QueryContext queryContext = CreateQueryContext(arguments);
object table = GetSource(queryContext);
IList result = null;
if (_selectResult != null) {
try {
IQueryable query = QueryableDataSourceHelper.AsQueryable(_selectResult);
query = ExecuteQuery(query, queryContext);
Type dataObjectType = GetDataObjectType(query.GetType());
result = query.ToList(dataObjectType);
if (_storeOriginalValues) {
ITable dlinqTable = table as ITable;
// We can store original values if the type is exact or derived
if ((dlinqTable != null) && dataObjectType.IsAssignableFrom(EntityType)) {
StoreOriginalValues(result);
}
}
}
catch (Exception e) {
result = null;
LinqDataSourceStatusEventArgs selectedEventArgs = new LinqDataSourceStatusEventArgs(e);
OnSelected(selectedEventArgs);
OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Select));
if (!selectedEventArgs.ExceptionHandled) {
throw;
}
}
finally {
if (result != null) {
int totalRowCount = -1; // paging performed, but row count not available.
if (arguments.RetrieveTotalRowCount) {
totalRowCount = arguments.TotalRowCount;
}
else if (!AutoPage) {
totalRowCount = result.Count;
}
LinqDataSourceStatusEventArgs selectedEventArgs = new LinqDataSourceStatusEventArgs(result, totalRowCount);
OnSelected(selectedEventArgs);
}
}
// Null out the select context
Context = null;
}
return result;
}
protected override object GetSource(QueryContext context) {
LinqDataSourceSelectEventArgs selectEventArgs = new LinqDataSourceSelectEventArgs(
context.Arguments,
context.WhereParameters,
context.OrderByParameters,
context.GroupByParameters,
context.OrderGroupsByParameters,
context.SelectParameters);
OnSelecting(selectEventArgs);
if (selectEventArgs.Cancel) {
return null;
}
_selectResult = selectEventArgs.Result;
object table = _selectResult;
// Original values should only be stored for valid delete and update scenarios.
_storeOriginalValues = StoreOriginalValuesInViewState && (CanDelete || CanUpdate) &&
String.IsNullOrEmpty(GroupBy) && String.IsNullOrEmpty(SelectNew);
if (_selectResult == null) {
table = base.GetSource(context);
_selectResult = table;
}
// If the provided select result was not a DLinq table and we need to store
// original values then we must get the table and create a new data context
// instance so that we can access the column metadata.
else if (!(table is ITable) && _storeOriginalValues) {
table = base.GetSource(context);
}
return table;
}
protected virtual MemberInfo GetTableMemberInfo(Type contextType) {
string tableName = TableName;
if (String.IsNullOrEmpty(tableName)) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_TableNameNotSpecified, _owner.ID));
}
MemberInfo[] members = contextType.FindMembers(MemberTypes.Field | MemberTypes.Property,
BindingFlags.Public | BindingFlags.Instance |
BindingFlags.Static, /*filter*/null, /*filterCriteria*/null);
for (int i = 0; i < members.Length; i++) {
if (String.Equals(members[i].Name, tableName, StringComparison.OrdinalIgnoreCase)) {
return members[i];
}
}
return null;
}
private ReadOnlyCollection<MetaDataMember> GetTableMetaDataMembers(ITable table, Type dataObjectType) {
DataContext context = ((ITable)table).Context;
MetaModel contextMetaData = context.Mapping;
MetaTable tableMetaData = contextMetaData.GetTable(dataObjectType);
MetaType rowMetaData = tableMetaData.Model.GetMetaType(dataObjectType);
return rowMetaData.DataMembers;
}
protected override void HandleValidationErrors(IDictionary<string, Exception> errors, DataSourceOperation operation) {
LinqDataSourceValidationException exception = new LinqDataSourceValidationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_ValidationFailed,
EntityType, errors.Values.First().Message),
errors);
bool exceptionHandled = false;
switch (operation) {
case DataSourceOperation.Delete:
LinqDataSourceDeleteEventArgs deleteEventArgs = new LinqDataSourceDeleteEventArgs(exception);
OnDeleting(deleteEventArgs);
OnException(new DynamicValidatorEventArgs(exception, DynamicDataSourceOperation.Delete));
exceptionHandled = deleteEventArgs.ExceptionHandled;
break;
case DataSourceOperation.Insert:
LinqDataSourceInsertEventArgs insertEventArgs = new LinqDataSourceInsertEventArgs(exception);
OnInserting(insertEventArgs);
OnException(new DynamicValidatorEventArgs(exception, DynamicDataSourceOperation.Insert));
exceptionHandled = insertEventArgs.ExceptionHandled;
break;
case DataSourceOperation.Update:
// allow user to handle conversion or dlinq property validation exceptions.
LinqDataSourceUpdateEventArgs updateEventArgs = new LinqDataSourceUpdateEventArgs(exception);
OnUpdating(updateEventArgs);
OnException(new DynamicValidatorEventArgs(exception, DynamicDataSourceOperation.Update));
exceptionHandled = updateEventArgs.ExceptionHandled;
break;
}
if (!exceptionHandled) {
throw exception;
}
}
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "object",
Justification = "Names are consistent with those used in the ObjectDataSource classes")]
protected virtual void InsertDataObject(object dataContext, object table, object newDataObject) {
_linqToSql.Add((ITable)table, newDataObject);
_linqToSql.SubmitChanges((DataContext)dataContext);
}
protected override int InsertObject(object newEntity) {
LinqDataSourceInsertEventArgs insertEventArgs = new LinqDataSourceInsertEventArgs(newEntity);
OnInserting(insertEventArgs);
if (insertEventArgs.Cancel) {
return -1;
}
LinqDataSourceStatusEventArgs insertedEventArgs = null;
try {
InsertDataObject(Context, EntitySet, insertEventArgs.NewObject);
}
catch (Exception e) {
// allow user to handle dlinq exceptions including OnValidate validation.
insertedEventArgs = new LinqDataSourceStatusEventArgs(e);
OnInserted(insertedEventArgs);
OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Insert));
if (insertedEventArgs.ExceptionHandled) {
return -1;
}
throw;
}
insertedEventArgs = new LinqDataSourceStatusEventArgs(insertEventArgs.NewObject);
OnInserted(insertedEventArgs);
return 1;
}
private static bool MemberIsStatic(MemberInfo member) {
FieldInfo field = member as FieldInfo;
if (field != null) {
return field.IsStatic;
}
PropertyInfo property = member as PropertyInfo;
if (property != null) {
MethodInfo propertyGetter = property.GetGetMethod();
return ((propertyGetter != null) && propertyGetter.IsStatic);
}
return false;
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnContextCreated(LinqDataSourceStatusEventArgs e) {
EventHandler<LinqDataSourceStatusEventArgs> handler = (EventHandler<LinqDataSourceStatusEventArgs>)Events[EventContextCreated];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnContextCreating(LinqDataSourceContextEventArgs e) {
EventHandler<LinqDataSourceContextEventArgs> handler = (EventHandler<LinqDataSourceContextEventArgs>)Events[EventContextCreating];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnContextDisposing(LinqDataSourceDisposeEventArgs e) {
EventHandler<LinqDataSourceDisposeEventArgs> handler = (EventHandler<LinqDataSourceDisposeEventArgs>)Events[EventContextDisposing];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnDeleted(LinqDataSourceStatusEventArgs e) {
EventHandler<LinqDataSourceStatusEventArgs> handler =
(EventHandler<LinqDataSourceStatusEventArgs>)Events[EventDeleted];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnDeleting(LinqDataSourceDeleteEventArgs e) {
EventHandler<LinqDataSourceDeleteEventArgs> handler =
(EventHandler<LinqDataSourceDeleteEventArgs>)Events[EventDeleting];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnException(DynamicValidatorEventArgs e) {
EventHandler<DynamicValidatorEventArgs> handler = (EventHandler<DynamicValidatorEventArgs>)Events[EventException];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnInserted(LinqDataSourceStatusEventArgs e) {
EventHandler<LinqDataSourceStatusEventArgs> handler =
(EventHandler<LinqDataSourceStatusEventArgs>)Events[EventInserted];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnInserting(LinqDataSourceInsertEventArgs e) {
EventHandler<LinqDataSourceInsertEventArgs> handler =
(EventHandler<LinqDataSourceInsertEventArgs>)Events[EventInserting];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnSelected(LinqDataSourceStatusEventArgs e) {
EventHandler<LinqDataSourceStatusEventArgs> handler =
(EventHandler<LinqDataSourceStatusEventArgs>)Events[EventSelected];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnSelecting(LinqDataSourceSelectEventArgs e) {
EventHandler<LinqDataSourceSelectEventArgs> handler =
(EventHandler<LinqDataSourceSelectEventArgs>)Events[EventSelecting];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnUpdated(LinqDataSourceStatusEventArgs e) {
EventHandler<LinqDataSourceStatusEventArgs> handler =
(EventHandler<LinqDataSourceStatusEventArgs>)Events[EventUpdated];
if (handler != null) {
handler(this, e);
}
}
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnUpdating(LinqDataSourceUpdateEventArgs e) {
EventHandler<LinqDataSourceUpdateEventArgs> handler =
(EventHandler<LinqDataSourceUpdateEventArgs>)Events[EventUpdating];
if (handler != null) {
handler(this, e);
}
}
internal void ReleaseSelectContexts() {
if (_selectContexts != null) {
foreach (ContextDataSourceContextData contextData in _selectContexts) {
DisposeContext(contextData.Context);
}
}
}
[SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters",
Justification = "Names are consistent with those used in the ObjectDataSource classes")]
protected virtual void ResetDataObject(object table, object dataObject) {
// DevDiv Bugs 187705, and 114508: Resetting is no longer necessary because
// select has it's own context, but this method is kept for compatibility purposes.
// no-op
}
public IEnumerable Select(DataSourceSelectArguments arguments) {
return ExecuteSelect(arguments);
}
private Dictionary<string, Exception> SetDataObjectProperties(object oldDataObject, object newDataObject) {
Dictionary<string, Exception> validateExceptions = null;
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(oldDataObject);
foreach (PropertyDescriptor property in properties) {
if (property.PropertyType.IsSerializable && !property.IsReadOnly) {
object newValue = property.GetValue(newDataObject);
try {
property.SetValue(oldDataObject, newValue);
}
catch (Exception e) {
if (validateExceptions == null) {
validateExceptions = new Dictionary<string, Exception>(StringComparer.OrdinalIgnoreCase);
}
validateExceptions[property.Name] = e;
}
}
}
return validateExceptions;
}
[SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods",
Justification = "System.Data.Linq assembly will be changing to support partial trust.")]
protected override void StoreOriginalValues(IList results) {
Type entityType = EntityType;
IDictionary<string, MetaDataMember> columns = GetTableMetaDataMembers((ITable)EntitySet, entityType).ToDictionary(c => c.Member.Name);
StoreOriginalValues(results, p => columns.ContainsKey(p.Name) &&
(columns[p.Name].IsPrimaryKey ||
columns[p.Name].IsVersion ||
(columns[p.Name].UpdateCheck != UpdateCheck.Never)));
}
[SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters",
Justification = "Names are consistent with those used in the ObjectDataSource classes")]
protected virtual void UpdateDataObject(object dataContext, object table,
object oldDataObject, object newDataObject) {
_linqToSql.Attach((ITable)table, oldDataObject);
Dictionary<string, Exception> validateExceptions = SetDataObjectProperties(oldDataObject, newDataObject);
// package up dlinq validation exceptions into single exception.
if (validateExceptions != null) {
throw new LinqDataSourceValidationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_ValidationFailed, oldDataObject.GetType(), validateExceptions.Values.First().Message), validateExceptions);
}
_linqToSql.SubmitChanges((DataContext)dataContext);
}
protected override int UpdateObject(object oldEntity, object newEntity) {
LinqDataSourceUpdateEventArgs updateEventArgs = new LinqDataSourceUpdateEventArgs(oldEntity, newEntity);
OnUpdating(updateEventArgs);
if (updateEventArgs.Cancel) {
return -1;
}
LinqDataSourceStatusEventArgs updatedEventArgs = null;
try {
UpdateDataObject(Context, EntitySet, updateEventArgs.OriginalObject, updateEventArgs.NewObject);
}
catch (Exception e) {
ResetDataObject(EntitySet, updateEventArgs.OriginalObject);
// allow user to handle dlinq exceptions including OnValidate validation.
updatedEventArgs = new LinqDataSourceStatusEventArgs(e);
OnUpdated(updatedEventArgs);
OnException(new DynamicValidatorEventArgs(e, DynamicDataSourceOperation.Update));
if (updatedEventArgs.ExceptionHandled) {
return -1;
}
throw;
}
updatedEventArgs = new LinqDataSourceStatusEventArgs(updateEventArgs.NewObject);
OnUpdated(updatedEventArgs);
return 1;
}
protected virtual void ValidateContextType(Type contextType, bool selecting) {
if (!selecting && !typeof(DataContext).IsAssignableFrom(contextType)) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_InvalidContextType, _owner.ID));
}
}
protected virtual void ValidateDeleteSupported(IDictionary keys, IDictionary oldValues) {
if (!CanDelete) {
throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_DeleteNotSupported, _owner.ID));
}
ValidateEditSupported();
}
protected virtual void ValidateEditSupported() {
if (!String.IsNullOrEmpty(GroupBy)) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_GroupByNotSupportedOnEdit, _owner.ID));
}
if (!String.IsNullOrEmpty(SelectNew)) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_SelectNewNotSupportedOnEdit, _owner.ID));
}
}
protected virtual void ValidateInsertSupported(IDictionary values) {
if (!CanInsert) {
throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_InsertNotSupported, _owner.ID));
}
ValidateEditSupported();
if ((values == null) || (values.Count == 0)) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_InsertRequiresValues, _owner.ID));
}
}
protected virtual void ValidateTableType(Type tableType, bool selecting) {
if (!selecting) {
if (!(tableType.IsGenericType && tableType.GetGenericArguments().Length == 1 && typeof(ITable).IsAssignableFrom(tableType))) {
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_InvalidTablePropertyType, _owner.ID));
}
}
}
protected virtual void ValidateUpdateSupported(IDictionary keys, IDictionary values, IDictionary oldValues) {
if (!CanUpdate) {
throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture,
AtlasWeb.LinqDataSourceView_UpdateNotSupported, _owner.ID));
}
ValidateEditSupported();
}
}
}
|