Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceChangedEventArgs.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner objsdev
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
namespace System.Web.UI.WebControls
{
public class EntityDataSourceChangedEventArgs : EventArgs
{
private readonly ObjectContext _context;
private readonly Exception _exception = null;
private bool _exceptionHandled = false;
private readonly object _entity = null;
internal EntityDataSourceChangedEventArgs(ObjectContext context, object entity)
{
_context = context;
_entity = entity;
}
internal EntityDataSourceChangedEventArgs(Exception exception)
{
_exception = exception;
}
public Exception Exception
{
get { return _exception; }
}
public bool ExceptionHandled
{
get { return _exceptionHandled; }
set { _exceptionHandled = value; }
}
public object Entity
{
get { return _entity; }
}
public ObjectContext Context
{
get { return _context; }
}
}
}

View File

@@ -0,0 +1,57 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceChangingEventArgs.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner objsdev
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
namespace System.Web.UI.WebControls
{
public class EntityDataSourceChangingEventArgs : System.ComponentModel.CancelEventArgs
{
private readonly ObjectContext _context;
private readonly Exception _exception = null;
private bool _exceptionHandled = false;
private readonly object _entity = null;
internal EntityDataSourceChangingEventArgs(ObjectContext context, object entity)
{
_context = context;
_entity = entity;
}
internal EntityDataSourceChangingEventArgs(Exception exception)
{
_exception = exception;
}
public Exception Exception
{
get { return _exception; }
}
public bool ExceptionHandled
{
get { return _exceptionHandled; }
set { _exceptionHandled = value; }
}
public object Entity
{
get { return _entity; }
}
public ObjectContext Context
{
get { return _context; }
}
}
}

View File

@@ -0,0 +1,441 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceColumn.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.EntityClient;
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Objects.DataClasses;
using System.Data.Objects;
using System.Data;
using System.Runtime.CompilerServices;
namespace System.Web.UI.WebControls
{
/// <summary>
/// Represents a column in EntityDataSourceView.
/// </summary>
internal abstract class EntityDataSourceColumn
{
protected EntityDataSourceColumn(string displayName)
: this(displayName, (EntityDataSourceColumn)null)
{
}
protected EntityDataSourceColumn(string displayName, EntityDataSourceColumn controllingColumn)
{
EntityDataSourceUtil.CheckArgumentNull(displayName, "displayName");
this.DisplayName = displayName;
this.ControllingColumn = controllingColumn;
}
/// <summary>
/// Gets the display name for this column.
/// </summary>
internal readonly string DisplayName;
/// <summary>
/// Gets the column exposed to the user. For instance, the reference key
/// it.Order.OrderID might have a dependent it.OrderID where there is a
/// ReferentialConstraint.
/// </summary>
internal readonly EntityDataSourceColumn ControllingColumn;
/// <summary>
/// Gets value indicating whether the column should be exposed to the user.
/// </summary>
internal bool IsHidden
{
get
{
// Columns with dependents are not shown to the user. They are
// merely used to plumb values (e.g. via referential integrity
// constraints)
return this.ControllingColumn != null;
}
}
/// <summary>
/// Gets the CLR type for the column value.
/// </summary>
internal abstract Type ClrType { get; }
/// <summary>
/// Gets a value indicating whether the original value for the column
/// needs to be preserved.
/// </summary>
internal abstract bool IsInteresting { get; }
/// <summary>
/// Gets a value indicating whether the column can be modified. Can be
/// overridden by the collection (which may be readonly).
/// </summary>
internal abstract bool CanWrite { get; }
/// <summary>
/// Indicates whether this column can be assigned a value of null.
/// </summary>
internal abstract bool IsNullable { get; }
/// <summary>
/// Indicates whether this column represents a scalar type.
/// </summary>
internal abstract bool IsScalar { get; }
/// Returns an Entity-SQL representation of this column with respect
/// to entity parameter 'it'.
/// </summary>
/// <returns>Entity-SQL string.</returns>
internal abstract string GetEntitySqlValue();
internal abstract object GetValue(EntityDataSourceWrapper entity);
internal abstract void SetValue(EntityDataSourceWrapper entity, object value);
}
/// <summary>
/// An EntityDataSourceView column that is an entity type or complex type property.
/// </summary>
internal class EntityDataSourcePropertyColumn : EntityDataSourceColumn
{
private readonly EntityDataSourceMemberPath memberPath;
internal EntityDataSourcePropertyColumn(EntityDataSourceMemberPath memberPath)
: base(EntityDataSourceUtil.CheckArgumentNull(memberPath, "memberPath").GetDescription())
{
this.memberPath = memberPath;
}
internal override bool IsInteresting
{
get
{
// the member path knows if its interesting...
return this.memberPath.IsInteresting;
}
}
internal override bool CanWrite
{
get
{
// can always write
return true;
}
}
internal override bool IsNullable
{
get { return memberPath.IsNullable; }
}
internal override bool IsScalar
{
get { return memberPath.IsScalar; }
}
internal override Type ClrType
{
get { return this.memberPath.ClrType; }
}
override internal object GetValue(EntityDataSourceWrapper entity)
{
return this.memberPath.GetValue(entity);
}
override internal void SetValue(EntityDataSourceWrapper entity, object value)
{
this.memberPath.SetValue(entity, value);
}
internal override string GetEntitySqlValue()
{
return this.memberPath.GetEntitySqlValue();
}
public override string ToString()
{
return this.memberPath.ToString();
}
/// <summary>
/// Indicates whether this column represents a primary key value;
/// </summary>
internal bool IsKey
{
get { return memberPath.IsKey; }
}
}
/// <summary>
/// An EntityDataSourceView column
/// </summary>
internal class EntityDataSourceReferenceKeyColumn : EntityDataSourceColumn
{
private readonly EntityDataSourceReferenceGroup group;
private readonly EdmProperty keyMember;
private readonly Type clrType;
private readonly bool isNullable;
internal EntityDataSourceReferenceKeyColumn(MetadataWorkspace workspace, EntityDataSourceReferenceGroup group, EdmProperty keyMember, EntityDataSourceColumn dependent)
: base(CreateDisplayName(group, keyMember), dependent)
{
EntityDataSourceUtil.CheckArgumentNull(group, "group");
EntityDataSourceUtil.CheckArgumentNull(keyMember, "keyMember");
Debug.Assert(EntityDataSourceUtil.IsScalar(keyMember.TypeUsage.EdmType), "Expected primitive or enum type for key members.");
this.group = group;
this.keyMember = keyMember;
this.clrType = EntityDataSourceUtil.GetMemberClrType(workspace, keyMember);
// if the association end is optional (0..1), make sure the CLR type
// is also nullable
if (this.group.End.CorrespondingAssociationEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne)
{
this.clrType = EntityDataSourceUtil.MakeNullable(clrType);
this.isNullable = true;
}
}
internal override bool IsInteresting
{
get
{
// references are always interesting
return true;
}
}
internal override bool CanWrite
{
get
{
// references can always be written
return true;
}
}
internal override bool IsNullable
{
get { return this.isNullable; }
}
internal override bool IsScalar
{
get { return EntityDataSourceUtil.IsScalar(keyMember.TypeUsage.EdmType); }
}
internal override Type ClrType
{
get { return this.clrType; }
}
internal EntityDataSourceReferenceGroup Group
{
get { return this.group; }
}
internal EdmMember KeyMember
{
get { return this.keyMember; }
}
private static string CreateDisplayName(EntityDataSourceReferenceGroup group, EdmProperty keyMember)
{
EntityDataSourceUtil.CheckArgumentNull(group, "group");
EntityDataSourceUtil.CheckArgumentNull(keyMember, "keyMember");
NavigationProperty navigationProperty;
string result;
if (EntityDataSourceUtil.TryGetCorrespondingNavigationProperty(group.End.CorrespondingAssociationEndMember, out navigationProperty))
{
result = navigationProperty.Name + "." + keyMember.Name;
}
else
{
// if there is no Navigation property, use the TargetTole and KeyMember name
// TargetRole.KeyMember
result = group.End.Name + "." + keyMember.Name;
}
return result;
}
public override string ToString()
{
return String.Format(CultureInfo.InvariantCulture, "<Set = {0}, Role = {1}>",
this.group.End.ParentAssociationSet.Name, this.group.End.Name);
}
internal override object GetValue(EntityDataSourceWrapper entity)
{
EntityKey entityKey = this.Group.GetEntityKey(entity);
if (null == entityKey)
{
return null;
}
else
{
object value = null;
// loop through to find the correct keymember, take compound key into consideration
foreach (EntityKeyMember entityKeyValue in entityKey.EntityKeyValues)
{
if (entityKeyValue.Key == this.KeyMember.Name)
{
value = entityKeyValue.Value;
}
}
return value;
}
}
internal override void SetValue(EntityDataSourceWrapper entity, object value)
{
throw new InvalidOperationException(Strings.SetValueNotSupported);
}
internal override string GetEntitySqlValue()
{
// syntax: NAVIGATE(it, _association_type_name_, _target_role_name_)._key_member_
StringBuilder builder = new StringBuilder();
builder.Append("NAVIGATE(");
builder.Append(EntityDataSourceUtil.EntitySqlElementAlias);
builder.Append(", ");
builder.Append(EntityDataSourceUtil.CreateEntitySqlTypeIdentifier(this.Group.End.ParentAssociationSet.ElementType));
builder.Append(", ");
builder.Append(EntityDataSourceUtil.QuoteEntitySqlIdentifier(this.Group.End.CorrespondingAssociationEndMember.Name));
builder.Append(").");
builder.Append(EntityDataSourceUtil.QuoteEntitySqlIdentifier(this.keyMember.Name));
string result = builder.ToString();
return result;
}
}
internal abstract class EntityDataSourceReferenceValueColumn : EntityDataSourceColumn
{
private readonly NavigationProperty navigationProperty;
protected EntityDataSourceReferenceValueColumn(MetadataWorkspace ocWorkspace, NavigationProperty navigationProperty)
: base(EntityDataSourceUtil.CheckArgumentNull(navigationProperty, "navigationProperty").Name)
{
EntityDataSourceUtil.CheckArgumentNull(ocWorkspace, "ocWorkspace");
this.navigationProperty = navigationProperty;
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
internal static EntityDataSourceReferenceValueColumn Create(Type clrToType, MetadataWorkspace ocWorkspace, NavigationProperty navigationProperty)
{
EntityDataSourceUtil.CheckArgumentNull(clrToType, "clrToType");
Type columnType = typeof(EntityDataSourceReferenceValueColumn<>).MakeGenericType(clrToType);
EntityDataSourceReferenceValueColumn result = (EntityDataSourceReferenceValueColumn)Activator.CreateInstance(columnType, ocWorkspace, navigationProperty);
return result;
}
internal override bool CanWrite
{
get
{
// can never write to a navigation reference
return false;
}
}
internal override bool IsNullable
{
get { return navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne; }
}
protected NavigationProperty NavigationProperty
{
get { return this.navigationProperty; }
}
internal override bool IsScalar
{
get { return false; }
}
internal override string GetEntitySqlValue()
{
// it.NavigationPropertyName
string result = EntityDataSourceUtil.EntitySqlElementAlias + "." + EntityDataSourceUtil.QuoteEntitySqlIdentifier(this.navigationProperty.Name);
return result;
}
internal override bool IsInteresting
{
get
{
// a navigation reference is not written, so its original values aren't interesting
return false;
}
}
internal override void SetValue(EntityDataSourceWrapper entity, object value)
{
throw new InvalidOperationException(Strings.SetValueNotSupported);
}
}
internal class EntityDataSourceReferenceValueColumn<T> : EntityDataSourceReferenceValueColumn
where T : class
{
public EntityDataSourceReferenceValueColumn(MetadataWorkspace ocWorkspace, NavigationProperty navigationProperty)
: base(ocWorkspace, navigationProperty)
{
}
internal override object GetValue(EntityDataSourceWrapper entity)
{
object result;
EntityReference<T> reference = GetRelatedReference(entity);
if (reference.IsLoaded)
{
result = reference.Value;
}
else
{
result = null;
}
return result;
}
internal override Type ClrType
{
get
{
return typeof(T);
}
}
private EntityReference<T> GetRelatedReference(EntityDataSourceWrapper entity)
{
RelationshipManager relationshipManager = entity.RelationshipManager;
Debug.Assert(relationshipManager != null, "Coldn't retrieve a RelationshipManager");
EntityReference<T> reference = relationshipManager.GetRelatedReference<T>(
this.NavigationProperty.RelationshipType.FullName,
this.NavigationProperty.ToEndMember.Name);
return reference;
}
}
}

View File

@@ -0,0 +1,29 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceContextCreatedEventArgs.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner objsdev
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
namespace System.Web.UI.WebControls
{
public class EntityDataSourceContextCreatedEventArgs : EventArgs
{
private readonly ObjectContext _context;
internal EntityDataSourceContextCreatedEventArgs(ObjectContext context)
{
_context = context;
}
public ObjectContext Context
{
get { return _context; }
}
}
}

View File

@@ -0,0 +1,27 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceContextCreatingEventArgs.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner objsdev
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
namespace System.Web.UI.WebControls
{
public class EntityDataSourceContextCreatingEventArgs : EventArgs
{
private ObjectContext _context;
internal EntityDataSourceContextCreatingEventArgs() { }
public ObjectContext Context
{
get { return _context; }
set { _context = value; }
}
}
}

View File

@@ -0,0 +1,32 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceContextDisposingEventArgs.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner objsdev
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Data.Objects;
namespace System.Web.UI.WebControls
{
public class EntityDataSourceContextDisposingEventArgs : CancelEventArgs
{
private readonly ObjectContext _context = null;
internal EntityDataSourceContextDisposingEventArgs(ObjectContext instance)
{
_context = instance;
}
public ObjectContext Context
{
get { return _context; }
}
}
}

View File

@@ -0,0 +1,205 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceMemberPath.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.EntityClient;
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Data.Common;
using System.Data.Objects;
namespace System.Web.UI.WebControls
{
/// <summary>
/// A glorified linked list. Describes a chain of properties from a primitive
/// type to a root entity.
/// </summary>
class EntityDataSourceMemberPath
{
private readonly EdmProperty property;
private readonly PropertyInfo propertyInfo;
private readonly EntityDataSourceMemberPath parent;
private readonly bool isLocallyInteresting;
private readonly Type clrType;
private readonly bool isKey;
internal EntityDataSourceMemberPath(MetadataWorkspace ocWorkspace, EntityDataSourceMemberPath parent, EdmProperty property, bool isLocallyInteresting)
{
EntityDataSourceUtil.CheckArgumentNull(ocWorkspace, "ocWorkspace");
EntityDataSourceUtil.CheckArgumentNull(property, "property");
this.property = property;
this.parent = parent;
this.isLocallyInteresting = isLocallyInteresting;
this.clrType = EntityDataSourceUtil.GetMemberClrType(ocWorkspace, property);
this.isKey = IsPropertyAKey(property);
// retrieve PropertyInfo (with respect to parent CLR type)
StructuralType parentType = property.DeclaringType;
Type parentClrType = EntityDataSourceUtil.GetClrType(ocWorkspace, parentType);
this.propertyInfo = EntityDataSourceUtil.GetPropertyInfo(parentClrType, this.property.Name);
}
/// <summary>
/// Describes the member path in the form 'property1.property2...'. Use to
/// determine display name for nested properties in the EDSC.
/// </summary>
/// <returns>Description of the </returns>
internal string GetDescription()
{
string prefix = null == this.parent ? string.Empty : this.parent.GetDescription() + ".";
return prefix + this.property.Name;
}
/// <summary>
/// Indicates whether original values of this member should be preserved.
/// </summary>
internal bool IsInteresting
{
get
{
// a member path is interesting if anything along the path is interesting
return this.isLocallyInteresting || (null != this.parent && this.parent.IsInteresting);
}
}
/// <summary>
/// Indicates whether this member represents a primary key value.
/// </summary>
internal bool IsKey
{
get { return this.isKey; }
}
/// <summary>
/// Indicates whether this member can be assigned a value of null.
/// </summary>
internal bool IsNullable
{
get { return this.property.Nullable; }
}
internal bool IsScalar
{
get { return EntityDataSourceUtil.IsScalar(this.property.TypeUsage.EdmType); }
}
/// <summary>
/// Gets the CLR type of the last member in the path.
/// </summary>
internal Type ClrType
{
get { return this.clrType; }
}
internal object GetValue(EntityDataSourceWrapper entity)
{
object parentObjectValue = GetParentObjectValue(entity, false /* initialize */);
if (null == parentObjectValue)
{
// use convention that property of null is null
return null;
}
else
{
// get this property
object propertyValue = this.propertyInfo.GetValue(parentObjectValue, new object[] { });
return propertyValue;
}
}
internal void SetValue(EntityDataSourceWrapper entity, object value)
{
object parentObjectValue = GetParentObjectValue(entity, true /* initialize */);
// set property value on parent
this.propertyInfo.SetValue(parentObjectValue, value, new object[] { });
}
private object Initialize(EntityDataSourceWrapper entity)
{
// get parent's value
object parentObjectValue = GetParentObjectValue(entity, true /* initialize */);
// construct type instance for this property
object propertyValue = EntityDataSourceUtil.InitializeType(this.ClrType);
// set property
this.propertyInfo.SetValue(parentObjectValue, propertyValue, new object[] { });
return propertyValue;
}
private object GetParentObjectValue(EntityDataSourceWrapper entity, bool initialize)
{
// get parent's value
object parentObjectValue;
if (null == this.parent)
{
// at the top level, the entity is the value
parentObjectValue = entity.WrappedEntity;
}
else
{
parentObjectValue = this.parent.GetValue(entity);
if (null == parentObjectValue && initialize)
{
parentObjectValue = this.parent.Initialize(entity);
}
}
return parentObjectValue;
}
internal string GetEntitySqlValue()
{
// it.[member1].[member2]...
string prefix;
if (null != parent)
{
prefix = parent.GetEntitySqlValue();
}
else
{
prefix = EntityDataSourceUtil.EntitySqlElementAlias;
}
string eSql = prefix + "." + EntityDataSourceUtil.QuoteEntitySqlIdentifier(this.property.Name);
return eSql;
}
private bool IsPropertyAKey(EdmProperty property)
{
bool isKey = false;
EntityType entityType = property.DeclaringType as EntityType;
if (null != entityType)
{
isKey = entityType.KeyMembers.Contains(property);
}
return isKey;
}
public override string ToString()
{
string prefix = null == this.parent ? string.Empty : this.parent.ToString() + "->";
return prefix + this.property.Name;
}
}
}

View File

@@ -0,0 +1,303 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceQueryBuilder.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
namespace System.Web.UI.WebControls
{
using System.Collections;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Objects;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
internal abstract class EntityDataSourceQueryBuilder<T>
{
private readonly DataSourceSelectArguments _arguments;
private readonly string _commandText;
private readonly ObjectParameter[] _commandParameters;
private readonly string _whereExpression;
private readonly ObjectParameter[] _whereParameters;
private readonly string _entitySetQueryExpression;
private readonly OrderByBuilder _orderByBuilder;
private string _includePaths;
private TypeUsage _resultType;
private Nullable<int> _count;
protected EntityDataSourceQueryBuilder(DataSourceSelectArguments arguments,
string commandText, ObjectParameter[] commandParameters,
string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
OrderByBuilder orderByBuilder,
string includePaths)
{
_arguments = arguments;
_commandText = commandText;
_commandParameters = commandParameters;
_whereExpression = whereExpression;
_whereParameters = whereParameters;
_entitySetQueryExpression = entitySetQueryExpression;
_orderByBuilder = orderByBuilder;
_includePaths = includePaths;
}
internal delegate EntityDataSourceQueryBuilder<T> Creator(DataSourceSelectArguments arguments,
string commandText, ObjectParameter[] commandParameters,
string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
OrderByBuilder orderByBuilder,
string includePaths);
internal TypeUsage ResultType
{
get
{
Debug.Assert(_resultType != null, "ResultType is only valid after Build()");
return _resultType;
}
}
internal int TotalCount
{
get
{
Debug.Assert(_count.HasValue, "Count is not valid until after Build. And only then if computeCount is true");
return _count.Value;
}
}
internal IEnumerable Execute(ObjectQuery<T> queryT)
{
return (IEnumerable)(((IListSource)(queryT)).GetList());
}
internal ObjectQuery<T> BuildBasicQuery(ObjectContext context, bool computeCount)
{
ObjectQuery<T> queryT = QueryBuilderUtils.ConstructQuery<T>(context, _entitySetQueryExpression, _commandText, _commandParameters);
queryT = ApplyWhere(queryT);
queryT = ApplySelect(queryT); // Select and/or GroupBy application
_resultType = queryT.GetResultType();
return queryT;
}
internal ObjectQuery<T> CompleteBuild(ObjectQuery<T> queryT, ObjectContext context, bool computeCount, bool wasExtended)
{
if (computeCount)
{
_count = queryT.Count();
}
queryT = wasExtended ? ApplyQueryableOrderByAndPaging(queryT) : ApplyOrderByAndPaging(queryT);
queryT = ApplyIncludePaths(queryT);
return queryT;
}
private ObjectQuery<T> ApplyWhere(ObjectQuery<T> queryT)
{
if (!String.IsNullOrEmpty(_whereExpression))
{
queryT = queryT.Where(_whereExpression, _whereParameters);
}
return queryT;
}
protected abstract ObjectQuery<T> ApplySelect(ObjectQuery<T> queryT);
internal ObjectQuery<T> ApplyOrderBy(ObjectQuery<T> queryT)
{
string orderByClause;
ObjectParameter[] orderByParameters;
// Apply all possible ordering except the sort expression, because it might only be valid after the query has been extended
_orderByBuilder.Generate(_resultType, out orderByClause, out orderByParameters, false /*applySortExpression*/);
return String.IsNullOrEmpty(orderByClause) ? queryT : queryT.OrderBy(orderByClause, orderByParameters);
}
private ObjectQuery<T> ApplyOrderByAndPaging(ObjectQuery<T> queryT)
{
// This re-applys the order-by as part of the skip
string orderByClause;
ObjectParameter[] orderByParameters;
_orderByBuilder.Generate(_resultType, out orderByClause, out orderByParameters, true /*applySortExpression*/);
bool paging = _arguments.MaximumRows > 0 && _arguments.StartRowIndex >= 0;
var hasOrderByClause = !String.IsNullOrEmpty(orderByClause);
if (paging)
{
if (!hasOrderByClause)
{
throw new InvalidOperationException(Strings.EntityDataSourceQueryBuilder_PagingRequiresOrderBy);
}
queryT = queryT.Skip(orderByClause, _arguments.StartRowIndex.ToString(CultureInfo.InvariantCulture), orderByParameters).Top(_arguments.MaximumRows.ToString(CultureInfo.InvariantCulture), QueryBuilderUtils.EmptyObjectParameters);
}
else
{
if (hasOrderByClause)
{
queryT = queryT.OrderBy(orderByClause, orderByParameters);
}
}
return queryT;
}
private ObjectQuery<T> ApplyQueryableOrderByAndPaging(ObjectQuery<T> queryT)
{
queryT = _orderByBuilder.BuildQueryableOrderBy(queryT) as ObjectQuery<T>;
bool paging = _arguments.MaximumRows > 0 && _arguments.StartRowIndex >= 0;
if (paging)
{
queryT = queryT.Skip(_arguments.StartRowIndex).Take(_arguments.MaximumRows) as ObjectQuery<T>;
}
return queryT;
}
private ObjectQuery<T> ApplyIncludePaths(ObjectQuery<T> objectQuery)
{
if (!string.IsNullOrEmpty(_includePaths))
{
foreach (string include in _includePaths.Split(','))
{
string trimmedInclude = include.Trim();
if (!string.IsNullOrEmpty(trimmedInclude))
{
objectQuery = objectQuery.Include(trimmedInclude);
}
}
}
return objectQuery;
}
}
internal class EntityDataSourceObjectQueryBuilder<T> : EntityDataSourceQueryBuilder<T>
{
private EntityDataSourceObjectQueryBuilder(DataSourceSelectArguments arguments,
string commandText, ObjectParameter[] commandParameters,
string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
OrderByBuilder orderByBuilder,
string includePaths)
: base(arguments,
commandText, commandParameters,
whereExpression, whereParameters, entitySetQueryExpression,
selectExpression, groupByExpression, selectParameters,
orderByBuilder,
includePaths)
{
}
static internal EntityDataSourceQueryBuilder<T>.Creator GetCreator()
{
return Create;
}
static internal EntityDataSourceQueryBuilder<T> Create(DataSourceSelectArguments arguments,
string commandText, ObjectParameter[] commandParameters,
string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
OrderByBuilder orderByBuilder,
string includePaths)
{
return new EntityDataSourceObjectQueryBuilder<T>(arguments,
commandText, commandParameters,
whereExpression, whereParameters, entitySetQueryExpression,
selectExpression, groupByExpression, selectParameters,
orderByBuilder,
includePaths);
}
protected override ObjectQuery<T> ApplySelect(ObjectQuery<T> queryT)
{
return queryT;
}
}
internal class EntityDataSourceRecordQueryBuilder : EntityDataSourceQueryBuilder<DbDataRecord>
{
private readonly string _selectExpression;
private readonly string _groupByExpression;
private readonly ObjectParameter[] _selectParameters;
private EntityDataSourceRecordQueryBuilder(DataSourceSelectArguments arguments,
string commandText, ObjectParameter[] commandParameters,
string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
OrderByBuilder orderByBuilder,
string includePaths)
: base(arguments,
commandText, commandParameters,
whereExpression, whereParameters, entitySetQueryExpression,
selectExpression, groupByExpression, selectParameters,
orderByBuilder,
includePaths)
{
_selectExpression = selectExpression;
_groupByExpression = groupByExpression;
_selectParameters = selectParameters;
}
static internal EntityDataSourceQueryBuilder<DbDataRecord> Create(DataSourceSelectArguments arguments,
string commandText, ObjectParameter[] commandParameters,
string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
OrderByBuilder orderByBuilder,
string includePaths)
{
return new EntityDataSourceRecordQueryBuilder(arguments,
commandText, commandParameters,
whereExpression, whereParameters, entitySetQueryExpression,
selectExpression, groupByExpression, selectParameters,
orderByBuilder,
includePaths);
}
protected override ObjectQuery<DbDataRecord> ApplySelect(ObjectQuery<DbDataRecord> queryT)
{
Debug.Assert(!String.IsNullOrEmpty(_selectExpression), "Select expression should not be of zero length.");
if (!string.IsNullOrEmpty(_groupByExpression))
{
queryT = queryT.GroupBy(_groupByExpression, _selectExpression, _selectParameters);
}
else
{
queryT = queryT.Select(_selectExpression, _selectParameters);
}
return queryT;
}
}
internal static class QueryBuilderUtils
{
internal static readonly ObjectParameter[] EmptyObjectParameters = new ObjectParameter[] { };
internal static ObjectQuery<T> ConstructQuery<T>(ObjectContext context,
string entitySetQueryExpression,
string commandText,
ObjectParameter[] commandParameters)
{
string queryExpression;
ObjectParameter[] queryParameters;
if (!string.IsNullOrEmpty(commandText))
{
queryExpression = commandText;
queryParameters = commandParameters;
}
else
{
queryExpression = entitySetQueryExpression;
queryParameters = QueryBuilderUtils.EmptyObjectParameters;
}
return context.CreateQuery<T>(queryExpression, queryParameters);
}
}
}

View File

@@ -0,0 +1,141 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceReferenceGroup.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.EntityClient;
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Objects.DataClasses;
using System.Data.Objects;
using System.Data;
using System.Runtime.CompilerServices;
namespace System.Web.UI.WebControls
{
/// <summary>
/// Groups together reference columns pointing at the same association end.
/// </summary>
internal abstract class EntityDataSourceReferenceGroup
{
private readonly AssociationSetEnd end;
protected EntityDataSourceReferenceGroup(AssociationSetEnd end)
{
EntityDataSourceUtil.CheckArgumentNull(end, "end");
this.end = end;
}
internal AssociationSetEnd End { get { return this.end; } }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
internal static EntityDataSourceReferenceGroup Create(Type entityType, AssociationSetEnd end)
{
EntityDataSourceUtil.CheckArgumentNull(entityType, "entityType");
Type groupType = typeof(EntityDataSourceReferenceGroup<>).MakeGenericType(entityType);
return (EntityDataSourceReferenceGroup)Activator.CreateInstance(groupType, new object[] { end });
}
internal abstract void SetKeyValues(EntityDataSourceWrapper wrapper, Dictionary<string, object> newKeyValues);
internal abstract EntityKey GetEntityKey(EntityDataSourceWrapper entity);
}
internal class EntityDataSourceReferenceGroup<T> : EntityDataSourceReferenceGroup
where T : class
{
public EntityDataSourceReferenceGroup(AssociationSetEnd end)
: base(end)
{
}
internal override void SetKeyValues(EntityDataSourceWrapper wrapper, Dictionary<string, object> newKeyValues)
{
EntityDataSourceUtil.CheckArgumentNull(wrapper, "wrapper");
EntityReference<T> reference = GetRelatedReference(wrapper);
EntityKey originalEntityKeys = reference.EntityKey;
if (null != newKeyValues)
{
if(null != originalEntityKeys)
{
// mix the missing keys from the original values
foreach (var originalEntityKey in originalEntityKeys.EntityKeyValues)
{
object newKeyValue;
if (newKeyValues.TryGetValue(originalEntityKey.Key, out newKeyValue))
{
// if any part of the key is null, the EntityKey is null
if (null == newKeyValue)
{
newKeyValues = null;
break;
}
}
else
{
// add the original value for this partial key since it is not saved in the viewstate
newKeyValues.Add(originalEntityKey.Key, originalEntityKey.Value);
}
}
}
else
{
// what we have in the newKeyValues should be sufficient to set the key
// but if any value is null, the whole key is null
foreach (var newKey in newKeyValues)
{
if (null == newKey.Value)
{
newKeyValues = null;
break;
}
}
}
}
if (null == newKeyValues)
{
// if the entity key is a compound key, and if any partial key is null, then the entitykey is null
reference.EntityKey = null;
}
else
{
reference.EntityKey = new EntityKey(EntityDataSourceUtil.GetQualifiedEntitySetName(End.EntitySet), (IEnumerable<KeyValuePair<string, object>>)newKeyValues);
}
}
internal override EntityKey GetEntityKey(EntityDataSourceWrapper entity)
{
EntityKey key = GetRelatedReference(entity).EntityKey;
return key;
}
private EntityReference<T> GetRelatedReference(EntityDataSourceWrapper entity)
{
RelationshipManager relationshipManager = entity.RelationshipManager;
Debug.Assert(relationshipManager != null, "couldn't get a relationship manager");
EntityReference<T> reference = relationshipManager.GetRelatedReference<T>(
this.End.ParentAssociationSet.ElementType.FullName,
this.End.CorrespondingAssociationEndMember.Name);
return reference;
}
}
}

View File

@@ -0,0 +1,75 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceSelectedEventArgs.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner objsdev
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Collections;
namespace System.Web.UI.WebControls
{
public class EntityDataSourceSelectedEventArgs : EventArgs
{
private readonly ObjectContext _context;
private readonly Exception _exception = null;
private bool _exceptionHandled = false;
private readonly IEnumerable _results = null;
private readonly int _totalRowCount = 0;
private readonly DataSourceSelectArguments _selectArguments;
internal EntityDataSourceSelectedEventArgs(ObjectContext context,
IEnumerable results,
int totalRowCount,
DataSourceSelectArguments selectArgs)
{
_context = context;
_results = results;
_totalRowCount = totalRowCount;
_selectArguments = selectArgs;
}
internal EntityDataSourceSelectedEventArgs(Exception exception)
{
_exception = exception;
}
public Exception Exception
{
get { return _exception; }
}
public bool ExceptionHandled
{
get { return _exceptionHandled; }
set { _exceptionHandled = value; }
}
public IEnumerable Results
{
get { return _results; }
}
public ObjectContext Context
{
get { return _context; }
}
public int TotalRowCount
{
get { return _totalRowCount; }
}
public DataSourceSelectArguments SelectArguments
{
get { return _selectArguments; }
}
}
}

View File

@@ -0,0 +1,43 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceSelectingEventArgs.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner objsdev
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.Objects;
using System.ComponentModel;
using System.Data.Metadata.Edm;
namespace System.Web.UI.WebControls
{
public class EntityDataSourceSelectingEventArgs : System.ComponentModel.CancelEventArgs
{
private readonly EntityDataSource _dataSource;
private readonly DataSourceSelectArguments _selectArguments;
internal EntityDataSourceSelectingEventArgs(EntityDataSource dataSource, DataSourceSelectArguments selectArgs)
{
_dataSource = dataSource;
_selectArguments = selectArgs;
}
public EntityDataSource DataSource
{
get { return _dataSource; }
}
public DataSourceSelectArguments SelectArguments
{
get { return _selectArguments; }
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,137 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceValidationException.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using System.Web.DynamicData;
namespace System.Web.UI.WebControls
{
/// <summary>
/// Represents errors that occur when validating properties of a dynamic data source.
/// </summary>
[Serializable]
[SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors", Justification = "SerializeObjectState used instead")]
public sealed class EntityDataSourceValidationException : Exception, IDynamicValidatorException
{
/// <summary>
/// Exception state used to serialize/deserialize the exception in a safe manner.
/// </summary>
[NonSerialized]
private EntityDataSourceValidationExceptionState _state;
/// <summary>
/// Initializes a new instance of the <see cref="EntityDataSourceValidationException" /> class.
/// </summary>
public EntityDataSourceValidationException()
: base()
{
InitializeExceptionState(null);
}
/// <summary>
/// Initializes a new instance of the <see cref="EntityDataSourceValidationException" /> class.
/// </summary>
/// <param name="message">Exception message.</param>
public EntityDataSourceValidationException(string message)
: base(message)
{
InitializeExceptionState(null);
}
/// <summary>
/// Initializes a new instance of the <see cref="EntityDataSourceValidationException" /> class.
/// </summary>
/// <param name="message">Exception message.</param>
/// <param name="innerException">Inner exception.</param>
public EntityDataSourceValidationException(string message, Exception innerException)
: base(message, innerException)
{
InitializeExceptionState(null);
}
/// <summary>
/// Initializes a new instance of the <see cref="EntityDataSourceValidationException" /> class.
/// </summary>
/// <param name="message">Exception message.</param>
/// <param name="innerExceptions">Inner exceptions.</param>
internal EntityDataSourceValidationException(string message, Dictionary<string, Exception> innerExceptions)
: base(message)
{
InitializeExceptionState(innerExceptions);
}
/// <summary>
/// Initializes internal exception state.
/// </summary>
/// <param name="innerExceptions">Inner exceptions.</param>
private void InitializeExceptionState(Dictionary<string, Exception> innerExceptions)
{
_state = new EntityDataSourceValidationExceptionState(innerExceptions);
SubscribeToSerializeObjectState();
}
/// <summary>
/// Returns inner exceptions.
/// </summary>
IDictionary<string, Exception> IDynamicValidatorException.InnerExceptions
{
get { return _state.InnerExceptions; }
}
/// <summary>
/// Subscribes the SerializeObjectState event.
/// </summary>
private void SubscribeToSerializeObjectState()
{
SerializeObjectState += (exception, eventArgs) => eventArgs.AddSerializedState(_state);
}
/// <summary>
/// Holds the exception state that will be serialized when the exception is serialized.
/// </summary>
[Serializable]
private class EntityDataSourceValidationExceptionState : ISafeSerializationData
{
/// <summary>
/// Inner exceptions.
/// </summary>
private readonly Dictionary<string, Exception> _innerExceptions;
/// <summary>
/// Initializes a new instance of the <see cref="EntityDataSourceValidationExceptionState"/> class.
/// </summary>
/// <param name="innerExceptions"></param>
public EntityDataSourceValidationExceptionState(Dictionary<string, Exception> innerExceptions)
{
_innerExceptions = innerExceptions ?? new Dictionary<string, Exception>();
}
/// <summary>
/// Returns inner exceptions.
/// </summary>
public Dictionary<string, Exception> InnerExceptions
{
get
{
return _innerExceptions;
}
}
/// <summary>
/// Completes the deserialization.
/// </summary>
/// <param name="deserialized">The deserialized object.</param>
public void CompleteDeserialization(object deserialized)
{
((EntityDataSourceValidationException)deserialized)._state = this;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceViewSchema.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
namespace System.Web.UI.WebControls
{
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
internal class EntityDataSourceViewSchema : DataTable
{
internal EntityDataSourceViewSchema(EntityDataSourceWrapperCollection wrappers)
{
DataColumn column;
List<DataColumn> keys = new List<DataColumn>();
PropertyDescriptorCollection properties = wrappers.GetItemProperties(null);
MetadataWorkspace workspace = wrappers.Context.MetadataWorkspace;
foreach (EntityDataSourceWrapperPropertyDescriptor property in properties)
{
Type propertyType = property.PropertyType;
column = ConstructColumn(property);
column.AllowDBNull = property.Column.IsNullable;
EntityDataSourcePropertyColumn propertyColumn = property.Column as EntityDataSourcePropertyColumn;
if (null!= propertyColumn && propertyColumn.IsKey)
{
keys.Add(column);
}
Columns.Add(column);
}
this.PrimaryKey = keys.ToArray();
}
internal EntityDataSourceViewSchema(ITypedList typedList)
{
PropertyDescriptorCollection properties = typedList.GetItemProperties(null);
CreateColumnsFromPropDescs(properties, null);
}
internal EntityDataSourceViewSchema(IEnumerable results)
: this(results, null)
{
}
/// <summary>
/// Creates a view schema with a set of typed results and an optional set of keyName properties on those results
/// </summary>
internal EntityDataSourceViewSchema(IEnumerable results, string[] keyNames)
{
Type type = GetListItemType(results.GetType());
PropertyInfo[] infos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(type);
CreateColumnsFromPropDescs(properties, keyNames);
}
/// <summary>
/// Creates a set of DataTable columns from a collection of property descriptors and an optional
/// set of key names from metadata
/// </summary>
private void CreateColumnsFromPropDescs(PropertyDescriptorCollection properties, string[] keyNames)
{
List<DataColumn> keys = new List<DataColumn>();
foreach (PropertyDescriptor property in properties)
{
System.ComponentModel.BrowsableAttribute attr =
(System.ComponentModel.BrowsableAttribute)property.Attributes[typeof(System.ComponentModel.BrowsableAttribute)];
if (attr.Browsable)
{
DataColumn column = ConstructColumn(property);
// If there are keyNames, check if this column is one of the keys
if (keyNames != null && keyNames.Contains(column.ColumnName))
{
keys.Add(column);
}
this.Columns.Add(column);
}
}
if (keys.Count > 0)
{
this.PrimaryKey = keys.ToArray();
}
}
private static DataColumn ConstructColumn(PropertyDescriptor property)
{
DataColumn column = new DataColumn();
column.ColumnName = property.Name;
Type propertyType = property.PropertyType;
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
Type[] typeArguments = propertyType.GetGenericArguments();
Debug.Assert(typeArguments.Length == 1, "should only have one type argument from Nullable<> condition.");
column.DataType = typeArguments[0];
column.AllowDBNull = true;
}
else
{
column.DataType = propertyType;
column.AllowDBNull = !propertyType.IsValueType;
}
column.ReadOnly = property.IsReadOnly;
column.Unique = false;
column.AutoIncrement = false;
column.MaxLength = -1;
return column;
}
// see System.Data.Objects.DataRecordObjectView.cs
private static PropertyInfo GetTypedIndexer(Type type)
{
PropertyInfo indexer = null;
if (typeof(IList).IsAssignableFrom(type) ||
typeof(ITypedList).IsAssignableFrom(type) ||
typeof(IListSource).IsAssignableFrom(type))
{
System.Reflection.PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int idx = 0; idx < props.Length; idx++)
{
if (props[idx].GetIndexParameters().Length > 0 && props[idx].PropertyType != typeof(object))
{
indexer = props[idx];
//Prefer the standard indexer, if there is one
if (indexer.Name == "Item")
{
break;
}
}
}
}
return indexer;
}
// see System.Data.Objects.DataRecordObjectView.cs
private static Type GetListItemType(Type type)
{
Type itemType;
if (typeof(Array).IsAssignableFrom(type))
{
itemType = type.GetElementType();
}
else
{
PropertyInfo typedIndexer = GetTypedIndexer(type);
if (typedIndexer != null)
{
itemType = typedIndexer.PropertyType;
}
else
{
itemType = type;
}
}
return itemType;
}
}
}

View File

@@ -0,0 +1,209 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceWrapper.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Data;
using System.Configuration;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Reflection;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Collections.ObjectModel;
using System.Text;
using System.Web.UI;
namespace System.Web.UI.WebControls
{
/// <summary>
/// Wraps an entity displayed in the data source in an ICustomTypeDescriptor
/// implementation that flattens complex types and exposes references.
/// </summary>
internal class EntityDataSourceWrapper : ICustomTypeDescriptor
{
private readonly EntityDataSourceWrapperCollection _collection;
private readonly ObjectStateEntry _stateEntry;
internal EntityDataSourceWrapper(EntityDataSourceWrapperCollection collection, object trackedEntity)
{
EntityDataSourceUtil.CheckArgumentNull(collection, "collection");
EntityDataSourceUtil.CheckArgumentNull(trackedEntity, "trackedEntity");
this._collection = collection;
// retrieve state entry
if (!this._collection.Context.ObjectStateManager.TryGetObjectStateEntry(trackedEntity, out _stateEntry))
{
throw new ArgumentException(Strings.ComponentNotFromProperCollection, "trackedEntity");
}
}
/// <summary>
/// Gets entity wrapped by this type descriptor.
/// </summary>
internal object WrappedEntity
{
get
{
return this._stateEntry.Entity;
}
}
internal RelationshipManager RelationshipManager
{
get
{
return this._stateEntry.RelationshipManager;
}
}
/// <summary>
/// Gets collection containing this wrapper.
/// </summary>
internal EntityDataSourceWrapperCollection Collection
{
get { return this._collection; }
}
#region ICustomTypeDescriptor Implementation
System.ComponentModel.AttributeCollection System.ComponentModel.ICustomTypeDescriptor.GetAttributes() { return new System.ComponentModel.AttributeCollection(); }
string ICustomTypeDescriptor.GetClassName() { return null; }
string ICustomTypeDescriptor.GetComponentName() { return null; }
TypeConverter ICustomTypeDescriptor.GetConverter() { return null; }
EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() { return null; }
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() { return null; }
object ICustomTypeDescriptor.GetEditor(Type editorBaseType) { return null; }
EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { return null; }
EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { return null; }
public PropertyDescriptorCollection GetProperties()
{
return ((ITypedList)this._collection).GetItemProperties(null);
}
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
return ((ICustomTypeDescriptor)this).GetProperties();
}
object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
return this.WrappedEntity;
}
#endregion ICustomTypeDescriptor Implementation
/// <summary>
/// Use this method to set the properties on the wrapped entity
/// </summary>
/// <param name="propertiesFromViewState"></param>
/// <param name="wrapper"></param>
/// <param name="overwriteSameValue"></param>
internal void SetAllProperties(Dictionary<string, object> propertiesFromViewState, bool overwriteSameValue,
ref Dictionary<string, Exception> propertySettingExceptionsCaught)
{
// We aggregate the reference descriptors rather than setting them directly
// to account for compound keys (we need all components of the key to create
// an EntityKey that can be set on the EntityReference)
var referenceList = new List<KeyValuePair<EntityDataSourceReferenceKeyColumn, object>>();
foreach (EntityDataSourceWrapperPropertyDescriptor descriptor in _collection.AllPropertyDescriptors)
{
// figure out which display name to match for this descriptor
string displayName = descriptor.Column.DisplayName;
// if we have a controlling column, use its display name instead
if (descriptor.Column.ControllingColumn != null)
{
displayName = descriptor.Column.ControllingColumn.DisplayName;
}
object value;
if (propertiesFromViewState.TryGetValue(displayName, out value))
{
// get all changed ReferencePropertyDescriptor from ViewState
EntityDataSourceReferenceKeyColumn referenceColumn = descriptor.Column as EntityDataSourceReferenceKeyColumn;
// convert the value as needed
object adjustedValue = EntityDataSourceUtil.ConvertType(value, descriptor.PropertyType, descriptor.DisplayName);
if (null != referenceColumn)
{
referenceList.Add(new KeyValuePair<EntityDataSourceReferenceKeyColumn, object>(
referenceColumn, adjustedValue));
continue;
}
if (overwriteSameValue || adjustedValue != descriptor.GetValue(this))
{
if (EntityDataSourceUtil.NullCanBeAssignedTo(descriptor.PropertyType) || null != adjustedValue)
{
try
{
descriptor.SetValue(this, adjustedValue);
}
catch (Exception e)
{
// The property descriptor uses reflection to set the property. Therefore, the inner exception contains the actual message.
Exception exceptionToThrow = e;
if (e.InnerException != null)
{
exceptionToThrow = e.InnerException;
}
if (null == propertySettingExceptionsCaught)
{
propertySettingExceptionsCaught = new Dictionary<string, Exception>();
}
propertySettingExceptionsCaught.Add(descriptor.DisplayName, exceptionToThrow);
}
}
}
}
}
// aggregate setting for EntityKey
SetEntityKeyProperties(referenceList, overwriteSameValue);
}
private void SetEntityKeyProperties(
List<KeyValuePair<EntityDataSourceReferenceKeyColumn, object>> referenceList, bool overwriteSameValue)
{
EntityDataSourceUtil.CheckArgumentNull(referenceList, "referenceList");
var groups = referenceList.GroupBy(r => r.Key.Group);
foreach (var group in groups)
{
Dictionary<string, object> partialKeys = new Dictionary<string, object>();
foreach (KeyValuePair<EntityDataSourceReferenceKeyColumn, object> reference in group)
{
// convert the value as needed
EntityDataSourceReferenceKeyColumn column = reference.Key;
object keyValue = reference.Value;
if (null == keyValue)
{
partialKeys = null;
break;
}
partialKeys.Add(column.KeyMember.Name, keyValue);
}
// we only set the entitykey for once, although there might be more than one
// properties descriptor associated with the same entitykey
group.Key.SetKeyValues(this, partialKeys);
}
}
}
}

View File

@@ -0,0 +1,180 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceWrapperCollection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections;
using System.ComponentModel;
using System.Collections.Generic;
using System.Data.Metadata.Edm;
using System.Data.Mapping;
using System.Data.Objects;
using System.Reflection;
using System.Diagnostics;
using System.Data.Common;
using System.Data.Objects.DataClasses;
using System.Globalization;
using System.Data.EntityClient;
using System.Collections.ObjectModel;
namespace System.Web.UI.WebControls
{
/// <summary>
/// Summary description for EntityDataSourceWrapperCollection
/// </summary>
internal class EntityDataSourceWrapperCollection : IEnumerable, ICollection, ITypedList
{
private readonly ObjectContext _context;
private readonly List<EntityDataSourceWrapper> _wrapperList;
/// <summary>
/// Gets the property descriptors exposed to the user.
/// </summary>
private readonly PropertyDescriptorCollection _visiblePropertyDescriptors;
/// <summary>
/// Gets all property descriptors.
/// </summary>
internal readonly ReadOnlyCollection<EntityDataSourceWrapperPropertyDescriptor> AllPropertyDescriptors;
private readonly bool _isReadOnly;
private readonly Type _clrEntityType;
internal EntityDataSourceWrapperCollection(ObjectContext context, EntitySet entitySet, EntityType restrictedEntityType)
{
EntityDataSourceUtil.CheckArgumentNull(context, "context");
EntityDataSourceUtil.CheckArgumentNull(entitySet, "entitySet");
_context = context;
_wrapperList = new List<EntityDataSourceWrapper>();
// get handles on the relevant workspaces
MetadataWorkspace csWorkspace = ((EntityConnection)context.Connection).GetMetadataWorkspace();
MetadataWorkspace ocWorkspace = context.MetadataWorkspace;
// if no restricted type is given, we assume the entity set element type is exposed
EntityType entityType = restrictedEntityType ?? entitySet.ElementType;
_clrEntityType = EntityDataSourceUtil.GetClrType(ocWorkspace, entityType);
// if no restricted type is given and the set is polymorphic, make the collection readonly
if (null == restrictedEntityType &&
1 < EntityDataSourceUtil.GetTypeAndSubtypesOf(entityType, csWorkspace.GetItemCollection(DataSpace.CSpace), true).Count())
{
_isReadOnly = true;
}
// gather the properties
ReadOnlyCollection<EntityDataSourceColumn> columns = EntityDataSourceUtil.GetNamedColumns(csWorkspace, ocWorkspace, entitySet, entityType);
List<PropertyDescriptor> visiblePropertyDescriptors = new List<PropertyDescriptor>(columns.Count);
List<EntityDataSourceWrapperPropertyDescriptor> propertyDescriptors = new List<EntityDataSourceWrapperPropertyDescriptor>(columns.Count);
foreach (EntityDataSourceColumn column in columns)
{
var descriptor = new EntityDataSourceWrapperPropertyDescriptor(this, column);
propertyDescriptors.Add(descriptor);
// if the descriptor does not have a dependent, it is exposed to the user
if (!descriptor.Column.IsHidden)
{
visiblePropertyDescriptors.Add(descriptor);
}
}
_visiblePropertyDescriptors = new PropertyDescriptorCollection(visiblePropertyDescriptors.ToArray(), true);
AllPropertyDescriptors = propertyDescriptors.AsReadOnly();
}
internal EntityDataSourceWrapper AddWrappedEntity(object entity)
{
EntityDataSourceWrapper wrapper = new EntityDataSourceWrapper(this, entity);
this._wrapperList.Add(wrapper);
return wrapper;
}
#region IEnumerable Implementation
IEnumerator IEnumerable.GetEnumerator()
{
return this._wrapperList.GetEnumerator();
}
#endregion IEnumerable Implementation
#region ICollection Implementation
public int Count
{
get { return this._wrapperList.Count; }
}
public void CopyTo(Array array, int index)
{
((ICollection)this._wrapperList).CopyTo(array, index);
}
public bool IsSynchronized
{
get { return false; }
}
public object SyncRoot
{
get { return null; }
}
#endregion
#region ITypedList Implementation
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
if (null == listAccessors)
{
return this._visiblePropertyDescriptors ;
}
else
{
return null;// Implement this feature when we support traversing collections.
}
}
string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
{
return null;
}
#endregion
#region Internal properties
/// <summary>
/// Gets CLR type or base type for entities exposed in this collection.
/// </summary>
internal Type ClrEntityType
{
get { return _clrEntityType; }
}
/// <summary>
/// Indicates whether this configuration supports modifications.
/// </summary>
internal bool IsReadOnly
{
get { return _isReadOnly; }
}
/// <summary>
/// Gets object context tracking the contents of this collection.
/// </summary>
internal ObjectContext Context
{
get { return _context; }
}
#endregion
}
}

View File

@@ -0,0 +1,114 @@
//---------------------------------------------------------------------
// <copyright file="EntityDataSourceWrapperPropertyDescriptor.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Data;
using System.Configuration;
using System.ComponentModel;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Reflection;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Collections.ObjectModel;
using System.Text;
namespace System.Web.UI.WebControls
{
/// <summary>
/// Wrapper property descriptor that handles access of nested members and
/// entity reference keys.
/// </summary>
/// <remarks>
/// This class essentially glues together a wrapper collection (roughly speaking
/// the 'data' exposed by the control) and the column (which defines the metadata
/// and behaviors for the current property).
/// </remarks>
internal sealed class EntityDataSourceWrapperPropertyDescriptor : PropertyDescriptor
{
private readonly EntityDataSourceWrapperCollection _collection;
private readonly EntityDataSourceColumn _column;
internal EntityDataSourceWrapperPropertyDescriptor(EntityDataSourceWrapperCollection collection, EntityDataSourceColumn column)
: base(EntityDataSourceUtil.CheckArgumentNull(column, "column").DisplayName, new Attribute[] { })
{
EntityDataSourceUtil.CheckArgumentNull(collection, "collection");
_collection = collection;
_column = column;
}
internal EntityDataSourceColumn Column
{
get { return _column; }
}
public override Type ComponentType
{
get { return _collection.ClrEntityType; }
}
public override bool IsReadOnly
{
get { return _collection.IsReadOnly || !_column.CanWrite; }
}
public override Type PropertyType
{
get { return _column.ClrType; }
}
public override bool CanResetValue(object component)
{
return false;
}
public override void ResetValue(object component)
{
throw new InvalidOperationException(Strings.ValueNotResettable(this.ComponentType.Name));
}
public override object GetValue(object component)
{
return _column.GetValue(GetWrapper(component));
}
public override void SetValue(object component, object value)
{
if (IsReadOnly)
{
throw new InvalidOperationException(Strings.SetValueNotSupported);
}
_column.SetValue(GetWrapper(component), value);
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
private EntityDataSourceWrapper GetWrapper(object component)
{
// Validate that the component comes from the collection to which
// this descriptor is bound. Elements of the collection are
// non-null wrappers instances.
EntityDataSourceUtil.CheckArgumentNull(component, "component");
EntityDataSourceWrapper wrapper = component as EntityDataSourceWrapper;
if (null == wrapper || this._collection != wrapper.Collection)
{
throw new ArgumentException(Strings.ComponentNotFromProperCollection, "component");
}
return wrapper;
}
}
}

View File

@@ -0,0 +1,266 @@
//---------------------------------------------------------------------
// <copyright file="OrderByBuilder.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//---------------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data.Metadata.Edm;
using System.Data.Objects;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace System.Web.UI.WebControls
{
internal class OrderByBuilder
{
private readonly string _argsSortExpression;
private readonly EntityDataSourceWrapperCollection _wrapperCollection;
private readonly string _orderBy;
private readonly bool _autoGenerateOrderByClause;
private readonly ParameterCollection _orderByParameters;
private readonly EntityDataSource _owner;
private readonly bool _generateDefaultOrderByClause;
internal OrderByBuilder(string argsSortExpression,
EntityDataSourceWrapperCollection wrapperCollection,
string orderBy,
bool autoGenerateOrderByClause,
ParameterCollection orderByParameters,
bool generateDefaultOrderByClause,
EntityDataSource owner)
{
_argsSortExpression = argsSortExpression;
_wrapperCollection = wrapperCollection;
_orderBy = orderBy;
_autoGenerateOrderByClause = autoGenerateOrderByClause;
_orderByParameters = orderByParameters;
_owner = owner;
_generateDefaultOrderByClause = generateDefaultOrderByClause;
}
internal void Generate(TypeUsage tu, out string orderBy, out ObjectParameter[] orderByParameters, bool applySortExpression)
{
Debug.Assert(null != tu, "Type Usage cannot be null");
GenerateOrderByClause(tu, out orderBy, out orderByParameters, applySortExpression);
}
private void GenerateOrderByClause(TypeUsage tu, out string orderByClause, out ObjectParameter[] orderByObjectParameters, bool applySortExpression)
{
var orderByClauseBuilder = new StringBuilder();
if (applySortExpression)
{
// This sets the orderBy clause based on a clicked column header in the databound control.
AppendOrderByKey(orderByClauseBuilder, _argsSortExpression, Strings.EntityDataSourceView_ColumnHeader, tu);
}
// AutoGenerateOrderByClause is mutually exclusive with OrderBy.
// Only one of the following two if statements will execute.
if (_autoGenerateOrderByClause)
{
Debug.Assert(String.IsNullOrEmpty(_orderBy), "If AutoGenerateOrderByClause is true, then OrderBy cannot be set. This should have been caught by a runtime error check");
IOrderedDictionary paramValues = _orderByParameters.GetValues(_owner.HttpContext, _owner);
foreach (DictionaryEntry de in paramValues)
{
// Skip AutoGenerateOrderBy on expressions that have a null value.
if (!string.IsNullOrEmpty((string)(de.Value)))
{
if (0 < orderByClauseBuilder.Length)
{
orderByClauseBuilder.Append(", ");
}
AppendOrderByKey(orderByClauseBuilder, (string)(de.Value), Strings.EntityDataSourceView_AutoGenerateOrderByParameters, tu);
}
}
}
// Append the OrderBy expression, if it's nonzero length.
if (!String.IsNullOrEmpty(_orderBy))
{
orderByObjectParameters = _owner.GetOrderByParameters();
Debug.Assert(!_autoGenerateOrderByClause, "If OrderBy is set, AutoGenerateOrderBy must be false. This should have been caught by a runtime error check");
if (0 < orderByClauseBuilder.Length)
{
orderByClauseBuilder.Append(", ");
}
orderByClauseBuilder.Append(_orderBy);
}
else
{
orderByObjectParameters = new ObjectParameter[] { };
}
if (orderByClauseBuilder.Length==0 && _generateDefaultOrderByClause)
{
// This only occurs if there's no EntitySet, which means entities are not wrapped.
orderByClauseBuilder.Append(GenerateDefaultOrderByFromTypeUsage(tu));
}
orderByClause = orderByClauseBuilder.ToString();
}
private void AppendOrderByKey(StringBuilder orderByClauseBuilder, string expression, string errorText, TypeUsage tu)
{
if (!String.IsNullOrEmpty(expression))
{
string[] statements = expression.Split(',');
string spacer = String.Empty;
foreach (string statement in statements)
{
bool isAscending = true;
string columnName = ParseStatement(statement.Trim(), out isAscending);
if (String.IsNullOrEmpty(columnName))
{
throw new ArgumentException(Strings.EntityDataSourceView_EmptyPropertyName);
}
if (EntityDataSourceUtil.PropertyIsOnEntity(columnName, _wrapperCollection, null, tu))
{
orderByClauseBuilder.Append(spacer);
orderByClauseBuilder.Append(EntityDataSourceUtil.GetEntitySqlValueForColumnName(columnName, _wrapperCollection));
}
else // pass the sort expression through verbatim.
{
if (!columnName.StartsWith("it.", StringComparison.OrdinalIgnoreCase))
{
columnName = "it." + columnName;
}
orderByClauseBuilder.Append(spacer + columnName);
}
if (!isAscending)
{
orderByClauseBuilder.Append(c_esqlDescendingTail);
}
spacer = ",";
}
}
}
private const string c_esqlAscendingTail = " ASC";
private const string c_esqlDescendingTail = " DESC";
private static readonly string[] ascendingTails = new string[] { c_esqlAscendingTail, " ascending" };
private static readonly string[] descendingTails = new string[] { c_esqlDescendingTail, " descending" };
private static string ParseStatement(string statement, out bool isAscending)
{
foreach (string tail in descendingTails)
{
if (statement.EndsWith(tail, StringComparison.OrdinalIgnoreCase))
{
isAscending = false;
return statement.Substring(0, statement.Length - tail.Length);
}
}
foreach (string tail in ascendingTails)
{
if (statement.EndsWith(tail, StringComparison.OrdinalIgnoreCase))
{
isAscending = true;
return statement.Substring(0, statement.Length - tail.Length);
}
}
isAscending = true;
return statement;
}
private static IQueryable ExpandQueryableOrderBy(IQueryable source, string[] statements)
{
var expression = source.Expression;
var parameter = Expression.Parameter(source.ElementType, String.Empty);
for (int idx = 0; idx < statements.Length; idx++)
{
bool isAscending = true;
// Try LINQ ascending/descending suffix
string memberReference = ParseStatement(statements[idx], out isAscending);
bool isFirstOrderBy = (idx == 0);
var methodName = (isFirstOrderBy ? "OrderBy" : "ThenBy") + (isAscending ? String.Empty : "Descending");
// Unravel nested property accesses
var memberElements = memberReference.Split('.');
Expression memberExpression = parameter;
foreach (string memberElement in memberElements)
{
if (string.IsNullOrEmpty(memberElement))
{
throw new ArgumentException(Strings.EntityDataSourceView_EmptyPropertyName);
}
memberExpression = Expression.Property(memberExpression, memberElement.Trim());
}
expression = Expression.Call(typeof(Queryable), methodName, new Type[] { source.ElementType, memberExpression.Type },
new Expression[] { expression, Expression.Quote(DynamicExpression.Lambda(memberExpression, parameter)) });
}
return source.Provider.CreateQuery(expression);
}
internal IQueryable<TEntity> BuildQueryableOrderBy<TEntity>(IQueryable<TEntity> source)
{
IQueryable query = source;
// Process control's sort arguments if there are any
if (_argsSortExpression != null & _argsSortExpression.Trim().Length > 0)
{
string[] statements = _argsSortExpression.Split(',');
if (statements.Length > 0)
{
query = ExpandQueryableOrderBy(query, statements);
}
}
return query as IQueryable<TEntity>;
}
private static string GenerateDefaultOrderByFromTypeUsage(TypeUsage tu)
{
StringBuilder orderByBuilder = new StringBuilder();
ReadOnlyMetadataCollection<EdmProperty> propertyCollection;
List<string> keyMemberNames = null;
EntityType entityType = tu.EdmType as EntityType;
if (null != entityType)
{
ReadOnlyMetadataCollection<EdmMember> keyMembers;
keyMembers = entityType.KeyMembers;
keyMemberNames = new List<string>(entityType.KeyMembers.Count);
propertyCollection = entityType.Properties;
foreach (EdmMember edmMember in keyMembers)
{
keyMemberNames.Add(edmMember.Name);
}
}
else
{
return String.Empty;
}
foreach (EdmProperty property in propertyCollection)
{
if (keyMemberNames.Contains(property.Name) && EntityDataSourceUtil.IsScalar(property.TypeUsage.EdmType))
{
if (0 < orderByBuilder.Length)
{
orderByBuilder.Append(", ");
}
orderByBuilder.Append(EntityDataSourceUtil.EntitySqlElementAlias);
orderByBuilder.Append(".");
orderByBuilder.Append(EntityDataSourceUtil.QuoteEntitySqlIdentifier(property.Name));
}
}
return orderByBuilder.ToString();
}
}
}

Some files were not shown because too many files have changed in this diff Show More