Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity.Internal;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
/// <summary>
/// Returned by the ChangeTracker method of <see cref="DbContext" /> to provide access to features of
/// the context that are related to change tracking of entities.
/// </summary>
public class DbChangeTracker
{
#region Construction and fields
private readonly InternalContext _internalContext;
/// <summary>
/// Initializes a new instance of the <see cref="DbChangeTracker" /> class.
/// </summary>
/// <param name="internalContext"> The internal context. </param>
internal DbChangeTracker(InternalContext internalContext)
{
DebugCheck.NotNull(internalContext);
_internalContext = internalContext;
}
#endregion
#region Entity entries
/// <summary>
/// Gets <see cref="DbEntityEntry" /> objects for all the entities tracked by this context.
/// </summary>
/// <returns> The entries. </returns>
public IEnumerable<DbEntityEntry> Entries()
{
return
_internalContext.GetStateEntries().Select(
e => new DbEntityEntry(new InternalEntityEntry(_internalContext, e)));
}
/// <summary>
/// Gets <see cref="DbEntityEntry" /> objects for all the entities of the given type
/// tracked by this context.
/// </summary>
/// <typeparam name="TEntity"> The type of the entity. </typeparam>
/// <returns> The entries. </returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
public IEnumerable<DbEntityEntry<TEntity>> Entries<TEntity>() where TEntity : class
{
return
_internalContext.GetStateEntries<TEntity>().Select(
e => new DbEntityEntry<TEntity>(new InternalEntityEntry(_internalContext, e)));
}
#endregion
#region DetectChanges
/// <summary>
/// Detects changes made to the properties and relationships of POCO entities. Note that some types of
/// entity (such as change tracking proxies and entities that derive from
/// <see
/// cref="System.Data.Entity.Core.Objects.DataClasses.EntityObject" />
/// )
/// report changes automatically and a call to DetectChanges is not normally needed for these types of entities.
/// Also note that normally DetectChanges is called automatically by many of the methods of <see cref="DbContext" />
/// and its related classes such that it is rare that this method will need to be called explicitly.
/// However, it may be desirable, usually for performance reasons, to turn off this automatic calling of
/// DetectChanges using the AutoDetectChangesEnabled flag from <see cref="DbContext.Configuration" />.
/// </summary>
public void DetectChanges()
{
_internalContext.DetectChanges(force: true);
}
#endregion
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{
return base.ToString();
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return base.GetHashCode();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
}
}

View File

@@ -0,0 +1,191 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Data.Entity.Utilities;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// A non-generic version of the <see cref="DbCollectionEntry{TEntity, TProperty}" /> class.
/// </summary>
public class DbCollectionEntry : DbMemberEntry
{
#region Fields and constructors
private readonly InternalCollectionEntry _internalCollectionEntry;
/// <summary>
/// Creates a <see cref="DbCollectionEntry" /> from information in the given <see cref="InternalCollectionEntry" />.
/// Use this method in preference to the constructor since it may potentially create a subclass depending on
/// the type of member represented by the InternalCollectionEntry instance.
/// </summary>
/// <param name="internalCollectionEntry"> The internal collection entry. </param>
/// <returns> The new entry. </returns>
internal static DbCollectionEntry Create(InternalCollectionEntry internalCollectionEntry)
{
DebugCheck.NotNull(internalCollectionEntry);
return (DbCollectionEntry)internalCollectionEntry.CreateDbMemberEntry();
}
/// <summary>
/// Initializes a new instance of the <see cref="DbCollectionEntry" /> class.
/// </summary>
/// <param name="internalCollectionEntry"> The internal entry. </param>
internal DbCollectionEntry(InternalCollectionEntry internalCollectionEntry)
{
DebugCheck.NotNull(internalCollectionEntry);
_internalCollectionEntry = internalCollectionEntry;
}
#endregion
#region Name
/// <summary>
/// Gets the property name.
/// </summary>
/// <value> The property name. </value>
public override string Name
{
get { return _internalCollectionEntry.Name; }
}
#endregion
#region Current values
/// <summary>
/// Gets or sets the current value of the navigation property. The current value is
/// the entity that the navigation property references.
/// </summary>
/// <value> The current value. </value>
public override object CurrentValue
{
get { return _internalCollectionEntry.CurrentValue; }
set { _internalCollectionEntry.CurrentValue = value; }
}
#endregion
#region Loading
/// <summary>
/// Loads the collection of entities from the database.
/// Note that entities that already exist in the context are not overwritten with values from the database.
/// </summary>
public void Load()
{
_internalCollectionEntry.Load();
}
#if !NET40
/// <summary>
/// An asynchronous version of Load, which
/// loads the entity from the database.
/// Note that if the entity already exists in the context, then it will not overwritten with values from the database.
/// </summary>
/// <returns> A Task representing the asynchronous operation. </returns>
public Task LoadAsync()
{
return LoadAsync(CancellationToken.None);
}
/// <summary>
/// An asynchronous version of Load, which
/// loads the entity from the database.
/// Note that if the entity already exists in the context, then it will not overwritten with values from the database.
/// </summary>
/// <param name="cancellationToken"> The token to monitor for cancellation requests. </param>
/// <returns> A Task representing the asynchronous operation. </returns>
public Task LoadAsync(CancellationToken cancellationToken)
{
return _internalCollectionEntry.LoadAsync(cancellationToken);
}
#endif
/// <summary>
/// Gets a value indicating whether the collection of entities has been loaded from the database.
/// </summary>
/// <value>
/// <c>true</c> if the collection is loaded; otherwise, <c>false</c> .
/// </value>
public bool IsLoaded
{
get { return _internalCollectionEntry.IsLoaded; }
}
/// <summary>
/// Returns the query that would be used to load this collection from the database.
/// The returned query can be modified using LINQ to perform filtering or operations in the database, such
/// as counting the number of entities in the collection in the database without actually loading them.
/// </summary>
/// <returns> A query for the collection. </returns>
public IQueryable Query()
{
return _internalCollectionEntry.Query();
}
#endregion
#region Back references
/// <summary>
/// The <see cref="DbEntityEntry" /> to which this navigation property belongs.
/// </summary>
/// <value> An entry for the entity that owns this navigation property. </value>
public override DbEntityEntry EntityEntry
{
get { return new DbEntityEntry(_internalCollectionEntry.InternalEntityEntry); }
}
#endregion
#region InternalMemberEntry access
/// <summary>
/// Gets the <see cref="InternalCollectionEntry" /> backing this object as an <see cref="InternalMemberEntry" />.
/// </summary>
/// <value> The internal member entry. </value>
internal override InternalMemberEntry InternalMemberEntry
{
get { return _internalCollectionEntry; }
}
#endregion
#region Conversion to generic
/// <summary>
/// Returns the equivalent generic <see cref="DbCollectionEntry{TEntity,TElement}" /> object.
/// </summary>
/// <typeparam name="TEntity"> The type of entity on which the member is declared. </typeparam>
/// <typeparam name="TElement"> The type of the collection element. </typeparam>
/// <returns> The equivalent generic object. </returns>
public new DbCollectionEntry<TEntity, TElement> Cast<TEntity, TElement>() where TEntity : class
{
var metadata = _internalCollectionEntry.EntryMetadata;
if (!typeof(TEntity).IsAssignableFrom(metadata.DeclaringType)
|| !typeof(TElement).IsAssignableFrom(metadata.ElementType))
{
throw Error.DbMember_BadTypeForCast(
typeof(DbCollectionEntry).Name,
typeof(TEntity).Name,
typeof(TElement).Name,
metadata.DeclaringType.Name,
metadata.ElementType.Name);
}
return DbCollectionEntry<TEntity, TElement>.Create(_internalCollectionEntry);
}
#endregion
}
}

View File

@@ -0,0 +1,194 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections.Generic;
using System.Data.Entity.Internal;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Instances of this class are returned from the Collection method of
/// <see cref="DbEntityEntry{T}" /> and allow operations such as loading to
/// be performed on the an entity's collection navigation properties.
/// </summary>
/// <typeparam name="TEntity"> The type of the entity to which this property belongs. </typeparam>
/// <typeparam name="TElement"> The type of the element in the collection of entities. </typeparam>
public class DbCollectionEntry<TEntity, TElement> : DbMemberEntry<TEntity, ICollection<TElement>>
where TEntity : class
{
#region Fields and constructors
private readonly InternalCollectionEntry _internalCollectionEntry;
/// <summary>
/// Creates a <see cref="DbCollectionEntry{TEntity,TElement}" /> from information in the given
/// <see
/// cref="InternalCollectionEntry" />
/// .
/// Use this method in preference to the constructor since it may potentially create a subclass depending on
/// the type of member represented by the InternalCollectionEntry instance.
/// </summary>
/// <param name="internalCollectionEntry"> The internal collection entry. </param>
/// <returns> The new entry. </returns>
internal static DbCollectionEntry<TEntity, TElement> Create(InternalCollectionEntry internalCollectionEntry)
{
DebugCheck.NotNull(internalCollectionEntry);
// Note that the implementation of this Create method is different than for the other DbMemberEntry classes.
// This is because the DbMemberEntry is defined in terms of the ICollection<TElement> while this class
// is defined in terms of just TElement. This means that we can't just call the CreateDbMemberEntry factory
// method on InternalMemberEntry. Instead we call the special factory method on InternalCollectionEntry.
return internalCollectionEntry.CreateDbCollectionEntry<TEntity, TElement>();
}
/// <summary>
/// Initializes a new instance of the <see cref="DbCollectionEntry{TEntity, TProperty}" /> class.
/// </summary>
/// <param name="internalCollectionEntry"> The internal entry. </param>
internal DbCollectionEntry(InternalCollectionEntry internalCollectionEntry)
{
DebugCheck.NotNull(internalCollectionEntry);
_internalCollectionEntry = internalCollectionEntry;
}
#endregion
#region Name
/// <summary>
/// Gets the property name.
/// </summary>
/// <value> The property name. </value>
public override string Name
{
get { return _internalCollectionEntry.Name; }
}
#endregion
#region Current values
/// <summary>
/// Gets or sets the current value of the navigation property. The current value is
/// the entity that the navigation property references.
/// </summary>
/// <value> The current value. </value>
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public override ICollection<TElement> CurrentValue
{
get { return (ICollection<TElement>)_internalCollectionEntry.CurrentValue; }
set { _internalCollectionEntry.CurrentValue = value; }
}
#endregion
#region Loading
/// <summary>
/// Loads the collection of entities from the database.
/// Note that entities that already exist in the context are not overwritten with values from the database.
/// </summary>
public void Load()
{
_internalCollectionEntry.Load();
}
#if !NET40
/// <summary>
/// An asynchronous version of Load, which
/// loads the entity from the database.
/// Note that if the entity already exists in the context, then it will not overwritten with values from the database.
/// </summary>
/// <returns> A Task representing the asynchronous operation. </returns>
public Task LoadAsync()
{
return LoadAsync(CancellationToken.None);
}
/// <summary>
/// An asynchronous version of Load, which
/// loads the entity from the database.
/// Note that if the entity already exists in the context, then it will not overwritten with values from the database.
/// </summary>
/// <param name="cancellationToken"> The token to monitor for cancellation requests. </param>
/// <returns> A Task representing the asynchronous operation. </returns>
public Task LoadAsync(CancellationToken cancellationToken)
{
return _internalCollectionEntry.LoadAsync(cancellationToken);
}
#endif
/// <summary>
/// Gets a value indicating whether the collection of entities has been loaded from the database.
/// </summary>
/// <value>
/// <c>true</c> if the collection is loaded; otherwise, <c>false</c> .
/// </value>
public bool IsLoaded
{
get { return _internalCollectionEntry.IsLoaded; }
}
/// <summary>
/// Returns the query that would be used to load this collection from the database.
/// The returned query can be modified using LINQ to perform filtering or operations in the database, such
/// as counting the number of entities in the collection in the database without actually loading them.
/// </summary>
/// <returns> A query for the collection. </returns>
public IQueryable<TElement> Query()
{
return (IQueryable<TElement>)_internalCollectionEntry.Query();
}
#endregion
#region Conversion to non-generic
/// <summary>
/// Returns a new instance of the non-generic <see cref="DbCollectionEntry" /> class for
/// the navigation property represented by this object.
/// </summary>
/// <returns> A non-generic version. </returns>
[SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",
Justification = "Intentionally just implicit to reduce API clutter.")]
public static implicit operator DbCollectionEntry(DbCollectionEntry<TEntity, TElement> entry)
{
return DbCollectionEntry.Create(entry._internalCollectionEntry);
}
#endregion
#region Internal entry access
/// <summary>
/// Gets the underlying <see cref="InternalCollectionEntry" /> as an <see cref="InternalMemberEntry" />.
/// </summary>
/// <value> The internal member entry. </value>
internal override InternalMemberEntry InternalMemberEntry
{
get { return _internalCollectionEntry; }
}
#endregion
#region Back references
/// <summary>
/// The <see cref="DbEntityEntry{TEntity}" /> to which this navigation property belongs.
/// </summary>
/// <value> An entry for the entity that owns this navigation property. </value>
public override DbEntityEntry<TEntity> EntityEntry
{
get { return new DbEntityEntry<TEntity>(_internalCollectionEntry.InternalEntityEntry); }
}
#endregion
}
}

View File

@@ -0,0 +1,156 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections.Concurrent;
using System.Data.Common;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
/// <summary>
/// An immutable representation of an Entity Data Model (EDM) model that can be used to create an
/// <see cref="ObjectContext" /> or can be passed to the constructor of a <see cref="DbContext" />.
/// For increased performance, instances of this type should be cached and re-used to construct contexts.
/// </summary>
public class DbCompiledModel
{
#region Fields and constructors
// Cached delegates that have been created dynamically to call a constructors for a given derived type of ObjectContext.
private static readonly ConcurrentDictionary<Type, Func<EntityConnection, ObjectContext>> _contextConstructors =
new ConcurrentDictionary<Type, Func<EntityConnection, ObjectContext>>();
// Delegate to create an instance of a non-derived ObjectContext.
private static readonly Func<EntityConnection, ObjectContext> _objectContextConstructor =
c => new ObjectContext(c);
// An object that can be used to get a cached MetadataWorkspace.
private readonly ICachedMetadataWorkspace _workspace;
private readonly DbModelBuilder _cachedModelBuilder;
/// <summary>
/// For mocking.
/// </summary>
internal DbCompiledModel()
{
}
/// <summary>
/// Creates a model for the given EDM metadata model.
/// </summary>
/// <param name="modelaseMapping"> The EDM metadata model. </param>
internal DbCompiledModel(DbModel model)
{
DebugCheck.NotNull(model);
_workspace = new CodeFirstCachedMetadataWorkspace(model.DatabaseMapping);
_cachedModelBuilder = model.CachedModelBuilder;
}
#endregion
#region Model/database metadata
/// <summary>
/// A snapshot of the <see cref="DbModelBuilder" /> that was used to create this compiled model.
/// </summary>
internal virtual DbModelBuilder CachedModelBuilder
{
get { return _cachedModelBuilder; }
}
/// <summary>
/// The provider info (provider name and manifest token) that was used to create this model.
/// </summary>
internal virtual DbProviderInfo ProviderInfo
{
get { return _workspace.ProviderInfo; }
}
public string DefaultSchema
{
get { return CachedModelBuilder.ModelConfiguration.DefaultSchema; }
}
#endregion
#region CreateObjectContext
/// <summary>
/// Creates an instance of ObjectContext or class derived from ObjectContext. Note that an instance
/// of DbContext can be created instead by using the appropriate DbContext constructor.
/// If a derived ObjectContext is used, then it must have a public constructor with a single
/// EntityConnection parameter.
/// The connection passed is used by the ObjectContext created, but is not owned by the context. The caller
/// must dispose of the connection once the context has been disposed.
/// </summary>
/// <typeparam name="TContext"> The type of context to create. </typeparam>
/// <param name="existingConnection"> An existing connection to a database for use by the context. </param>
/// <returns> </returns>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
public TContext CreateObjectContext<TContext>(DbConnection existingConnection) where TContext : ObjectContext
{
Check.NotNull(existingConnection, "existingConnection");
var metadataWorkspace = _workspace.GetMetadataWorkspace(existingConnection);
var entityConnection = new EntityConnection(metadataWorkspace, existingConnection);
var context = (TContext)GetConstructorDelegate<TContext>()(entityConnection);
// Set the DefaultContainerName if it is empty
if (String.IsNullOrEmpty(context.DefaultContainerName))
{
context.DefaultContainerName = _workspace.DefaultContainerName;
}
foreach (var assembly in _workspace.Assemblies)
{
context.MetadataWorkspace.LoadFromAssembly(assembly);
}
return context;
}
/// <summary>
/// Gets a cached delegate (or creates a new one) used to call the constructor for the given derived ObjectContext type.
/// </summary>
internal static Func<EntityConnection, ObjectContext> GetConstructorDelegate<TContext>()
where TContext : ObjectContext
{
// Optimize for case where just ObjectContext (non-derived) is asked for.
if (typeof(TContext)
== typeof(ObjectContext))
{
return _objectContextConstructor;
}
Func<EntityConnection, ObjectContext> constructorDelegate;
if (!_contextConstructors.TryGetValue(typeof(TContext), out constructorDelegate))
{
var constructor = typeof(TContext).GetConstructor(
BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(EntityConnection) }, null);
if (constructor == null)
{
throw Error.DbModelBuilder_MissingRequiredCtor(typeof(TContext).Name);
}
var connectionParam = Expression.Parameter(typeof(EntityConnection), "connection");
constructorDelegate =
Expression.Lambda<Func<EntityConnection, ObjectContext>>(
Expression.New(constructor, connectionParam), connectionParam).
Compile();
_contextConstructors.TryAdd(typeof(TContext), constructorDelegate);
}
return constructorDelegate;
}
#endregion
}
}

View File

@@ -0,0 +1,105 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
/// <summary>
/// A non-generic version of the <see cref="DbComplexPropertyEntry{TEntity, TProperty}" /> class.
/// </summary>
public class DbComplexPropertyEntry : DbPropertyEntry
{
#region Fields and constructors
/// <summary>
/// Creates a <see cref="DbComplexPropertyEntry{TEntity,TComplexProperty}" /> from information in the given
/// <see
/// cref="InternalPropertyEntry" />
/// .
/// Use this method in preference to the constructor since it may potentially create a subclass depending on
/// the type of member represented by the InternalCollectionEntry instance.
/// </summary>
/// <param name="internalPropertyEntry"> The internal property entry. </param>
/// <returns> The new entry. </returns>
internal new static DbComplexPropertyEntry Create(InternalPropertyEntry internalPropertyEntry)
{
DebugCheck.NotNull(internalPropertyEntry);
return (DbComplexPropertyEntry)internalPropertyEntry.CreateDbMemberEntry();
}
/// <summary>
/// Initializes a new instance of the <see cref="DbPropertyEntry" /> class.
/// </summary>
/// <param name="internalPropertyEntry"> The internal entry. </param>
internal DbComplexPropertyEntry(InternalPropertyEntry internalPropertyEntry)
: base(internalPropertyEntry)
{
}
#endregion
#region Access to nested properties
/// <summary>
/// Gets an object that represents a nested property of this property.
/// This method can be used for both scalar or complex properties.
/// </summary>
/// <param name="propertyName"> The name of the nested property. </param>
/// <returns> An object representing the nested property. </returns>
public DbPropertyEntry Property(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return DbPropertyEntry.Create(((InternalPropertyEntry)InternalMemberEntry).Property(propertyName));
}
/// <summary>
/// Gets an object that represents a nested complex property of this property.
/// </summary>
/// <param name="propertyName"> The name of the nested property. </param>
/// <returns> An object representing the nested property. </returns>
[SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#",
Justification = "Rule predates more fluent naming conventions.")]
public DbComplexPropertyEntry ComplexProperty(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return
Create(((InternalPropertyEntry)InternalMemberEntry).Property(propertyName, null, requireComplex: true));
}
#endregion
#region Conversion to generic
/// <summary>
/// Returns the equivalent generic <see cref="DbComplexPropertyEntry{TEntity,TComplexProperty}" /> object.
/// </summary>
/// <typeparam name="TEntity"> The type of entity on which the member is declared. </typeparam>
/// <typeparam name="TComplexProperty"> The type of the complex property. </typeparam>
/// <returns> The equivalent generic object. </returns>
public new DbComplexPropertyEntry<TEntity, TComplexProperty> Cast<TEntity, TComplexProperty>()
where TEntity : class
{
var metadata = InternalMemberEntry.EntryMetadata;
if (!typeof(TEntity).IsAssignableFrom(metadata.DeclaringType)
|| !typeof(TComplexProperty).IsAssignableFrom(metadata.ElementType))
{
throw Error.DbMember_BadTypeForCast(
typeof(DbComplexPropertyEntry).Name,
typeof(TEntity).Name,
typeof(TComplexProperty).Name,
metadata.DeclaringType.Name,
metadata.MemberType.Name);
}
return DbComplexPropertyEntry<TEntity, TComplexProperty>.Create((InternalPropertyEntry)InternalMemberEntry);
}
#endregion
}
}

View File

@@ -0,0 +1,164 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Data.Entity.Internal;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
/// <summary>
/// Instances of this class are returned from the ComplexProperty method of
/// <see cref="DbEntityEntry{T}" /> and allow access to the state of a complex property.
/// </summary>
/// <typeparam name="TEntity"> The type of the entity to which this property belongs. </typeparam>
/// <typeparam name="TComplexProperty"> The type of the property. </typeparam>
public class DbComplexPropertyEntry<TEntity, TComplexProperty> : DbPropertyEntry<TEntity, TComplexProperty>
where TEntity : class
{
#region Fields and constructors
/// <summary>
/// Creates a <see cref="DbComplexPropertyEntry" /> from information in the given <see cref="InternalPropertyEntry" />.
/// Use this method in preference to the constructor since it may potentially create a subclass depending on
/// the type of member represented by the InternalCollectionEntry instance.
/// </summary>
/// <param name="internalPropertyEntry"> The internal property entry. </param>
/// <returns> The new entry. </returns>
internal new static DbComplexPropertyEntry<TEntity, TComplexProperty> Create(
InternalPropertyEntry internalPropertyEntry)
{
DebugCheck.NotNull(internalPropertyEntry);
return
(DbComplexPropertyEntry<TEntity, TComplexProperty>)
internalPropertyEntry.CreateDbMemberEntry<TEntity, TComplexProperty>();
}
/// <summary>
/// Initializes a new instance of the <see cref="DbComplexPropertyEntry{TEntity, TComplexProperty}" /> class.
/// </summary>
/// <param name="internalPropertyEntry"> The internal entry. </param>
internal DbComplexPropertyEntry(InternalPropertyEntry internalPropertyEntry)
: base(internalPropertyEntry)
{
}
#endregion
#region Conversion to non-generic
/// <summary>
/// Returns a new instance of the non-generic <see cref="DbComplexPropertyEntry" /> class for
/// the property represented by this object.
/// </summary>
/// <returns> A non-generic version. </returns>
[SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",
Justification = "Intentionally just implicit to reduce API clutter.")]
public static implicit operator DbComplexPropertyEntry(DbComplexPropertyEntry<TEntity, TComplexProperty> entry)
{
return DbComplexPropertyEntry.Create(entry.InternalPropertyEntry);
}
#endregion
#region Access to nested properties
/// <summary>
/// Gets an object that represents a nested property of this property.
/// This method can be used for both scalar or complex properties.
/// </summary>
/// <param name="propertyName"> The name of the nested property. </param>
/// <returns> An object representing the nested property. </returns>
public DbPropertyEntry Property(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return DbPropertyEntry.Create(InternalPropertyEntry.Property(propertyName));
}
/// <summary>
/// Gets an object that represents a nested property of this property.
/// This method can be used for both scalar or complex properties.
/// </summary>
/// <typeparam name="TNestedProperty"> The type of the nested property. </typeparam>
/// <param name="propertyName"> The name of the nested property. </param>
/// <returns> An object representing the nested property. </returns>
public DbPropertyEntry<TEntity, TNestedProperty> Property<TNestedProperty>(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return
DbPropertyEntry<TEntity, TNestedProperty>.Create(
InternalPropertyEntry.Property(propertyName, typeof(TNestedProperty)));
}
/// <summary>
/// Gets an object that represents a nested property of this property.
/// This method can be used for both scalar or complex properties.
/// </summary>
/// <typeparam name="TNestedProperty"> The type of the nested property. </typeparam>
/// <param name="navigationProperty"> An expression representing the nested property. </param>
/// <returns> An object representing the nested property. </returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
[SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#",
Justification = "Rule predates more fluent naming conventions.")]
public DbPropertyEntry<TEntity, TNestedProperty> Property<TNestedProperty>(
Expression<Func<TComplexProperty, TNestedProperty>> property)
{
Check.NotNull(property, "property");
return Property<TNestedProperty>(DbHelpers.ParsePropertySelector(property, "Property", "property"));
}
/// <summary>
/// Gets an object that represents a nested complex property of this property.
/// </summary>
/// <param name="propertyName"> The name of the nested property. </param>
/// <returns> An object representing the nested property. </returns>
public DbComplexPropertyEntry ComplexProperty(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return
DbComplexPropertyEntry.Create(InternalPropertyEntry.Property(propertyName, null, requireComplex: true));
}
/// <summary>
/// Gets an object that represents a nested complex property of this property.
/// </summary>
/// <typeparam name="TNestedComplexProperty"> The type of the nested property. </typeparam>
/// <param name="propertyName"> The name of the nested property. </param>
/// <returns> An object representing the nested property. </returns>
public DbComplexPropertyEntry<TEntity, TNestedComplexProperty> ComplexProperty<TNestedComplexProperty>(
string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return
DbComplexPropertyEntry<TEntity, TNestedComplexProperty>.Create(
InternalPropertyEntry.Property(propertyName, typeof(TNestedComplexProperty), requireComplex: true));
}
/// <summary>
/// Gets an object that represents a nested complex property of this property.
/// </summary>
/// <typeparam name="TNestedComplexProperty"> The type of the nested property. </typeparam>
/// <param name="navigationProperty"> An expression representing the nested property. </param>
/// <returns> An object representing the nested property. </returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
[SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#",
Justification = "Rule predates more fluent naming conventions.")]
public DbComplexPropertyEntry<TEntity, TNestedComplexProperty> ComplexProperty<TNestedComplexProperty>(
Expression<Func<TComplexProperty, TNestedComplexProperty>> property)
{
Check.NotNull(property, "property");
return
ComplexProperty<TNestedComplexProperty>(
DbHelpers.ParsePropertySelector(property, "Property", "property"));
}
#endregion
}
}

View File

@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.ComponentModel;
using System.Configuration;
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
/// <summary>
/// Represents information about a database connection.
/// </summary>
[Serializable]
public class DbConnectionInfo
{
private readonly string _connectionName;
private readonly string _connectionString;
private readonly string _providerInvariantName;
/// <summary>
/// Creates a new instance of DbConnectionInfo representing a connection that is specified in the application configuration file.
/// </summary>
/// <param name="connectionName"> The name of the connection string in the application configuration. </param>
public DbConnectionInfo(string connectionName)
{
Check.NotEmpty(connectionName, "connectionName");
_connectionName = connectionName;
}
/// <summary>
/// Creates a new instance of DbConnectionInfo based on a connection string.
/// </summary>
/// <param name="connectionString"> The connection string to use for the connection. </param>
/// <param name="providerInvariantName"> The name of the provider to use for the connection. Use 'System.Data.SqlClient' for SQL Server. </param>
public DbConnectionInfo(string connectionString, string providerInvariantName)
{
Check.NotEmpty(connectionString, "connectionString");
Check.NotEmpty(providerInvariantName, "providerInvariantName");
_connectionString = connectionString;
_providerInvariantName = providerInvariantName;
}
/// <summary>
/// Gets the connection information represented by this instance.
/// </summary>
/// <param name="config"> Configuration to use if connection comes from the configuration file. </param>
internal ConnectionStringSettings GetConnectionString(AppConfig config)
{
DebugCheck.NotNull(config);
if (_connectionName != null)
{
var result = config.GetConnectionString(_connectionName);
if (result == null)
{
throw Error.DbConnectionInfo_ConnectionStringNotFound(_connectionName);
}
return result;
}
return new ConnectionStringSettings(null, _connectionString, _providerInvariantName);
}
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{
return base.ToString();
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return base.GetHashCode();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
}
}

View File

@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
/// <summary>
/// Describes the origin of the database connection string associated with a <see cref="DbContext" />.
/// </summary>
public enum DbConnectionStringOrigin
{
/// <summary>
/// The connection string was created by convention.
/// </summary>
Convention,
/// <summary>
/// The connection string was read from external configuration.
/// </summary>
Configuration,
/// <summary>
/// The connection string was explicitly specified at runtime.
/// </summary>
UserCode,
/// <summary>
/// The connection string was overriden by connection information supplied to DbContextInfo.
/// </summary>
DbContextInfo
}
}

View File

@@ -0,0 +1,124 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.ComponentModel;
using System.Data.Entity.Internal;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
/// <summary>
/// Returned by the Configuration method of <see cref="DbContext" /> to provide access to configuration
/// options for the context.
/// </summary>
public class DbContextConfiguration
{
#region Construction and fields
private readonly InternalContext _internalContext;
/// <summary>
/// Initializes a new instance of the <see cref="DbContextConfiguration" /> class.
/// </summary>
/// <param name="internalContext"> The internal context. </param>
internal DbContextConfiguration(InternalContext internalContext)
{
DebugCheck.NotNull(internalContext);
_internalContext = internalContext;
}
#endregion
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{
return base.ToString();
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return base.GetHashCode();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
#region Configuration options
/// <summary>
/// Gets or sets a value indicating whether lazy loading of relationships exposed as
/// navigation properties is enabled. Lazy loading is enabled by default.
/// </summary>
/// <value>
/// <c>true</c> if lazy loading is enabled; otherwise, <c>false</c> .
/// </value>
public bool LazyLoadingEnabled
{
get { return _internalContext.LazyLoadingEnabled; }
set { _internalContext.LazyLoadingEnabled = value; }
}
/// <summary>
/// Gets or sets a value indicating whether or not the framework will create instances of
/// dynamically generated proxy classes whenever it creates an instance of an entity type.
/// Note that even if proxy creation is enabled with this flag, proxy instances will only
/// be created for entity types that meet the requirements for being proxied.
/// Proxy creation is enabled by default.
/// </summary>
/// <value>
/// <c>true</c> if proxy creation is enabled; otherwise, <c>false</c> .
/// </value>
public bool ProxyCreationEnabled
{
get { return _internalContext.ProxyCreationEnabled; }
set { _internalContext.ProxyCreationEnabled = value; }
}
/// <summary>
/// Gets or sets a value indicating whether the <see cref="DbContext.ChangeTracker.DetectChanges()" />
/// method is called automatically by methods of <see cref="DbContext" /> and related classes.
/// The default value is true.
/// </summary>
/// <value
/// <c>true</c>
/// if should be called automatically; otherwise,
/// <c>false</c>
/// .
/// </value>
public bool AutoDetectChangesEnabled
{
get { return _internalContext.AutoDetectChangesEnabled; }
set { _internalContext.AutoDetectChangesEnabled = value; }
}
/// <summary>
/// Gets or sets a value indicating whether tracked entities should be validated automatically when
/// <see cref="DbContext.SaveChanges()" /> is invoked.
/// The default value is true.
/// </summary>
public bool ValidateOnSaveEnabled
{
get { return _internalContext.ValidateOnSaveEnabled; }
set { _internalContext.ValidateOnSaveEnabled = value; }
}
#endregion
}
}

View File

@@ -0,0 +1,351 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Configuration;
using System.Data.Entity.Config;
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
/// <summary>
/// Provides runtime information about a given <see cref="DbContext" /> type.
/// </summary>
public class DbContextInfo
{
private readonly Type _contextType;
private readonly DbProviderInfo _modelProviderInfo;
private readonly DbConnectionInfo _connectionInfo;
private readonly AppConfig _appConfig;
private readonly Func<DbContext> _activator;
private readonly string _connectionString;
private readonly string _connectionProviderName;
private readonly bool _isConstructible;
private readonly DbConnectionStringOrigin _connectionStringOrigin;
private readonly string _connectionStringName;
private Action<DbModelBuilder> _onModelCreating;
/// <summary>
/// Creates a new instance representing a given <see cref="DbContext" /> type.
/// </summary>
/// <param name="contextType">
/// The type deriving from <see cref="DbContext" /> .
/// </param>
public DbContextInfo(Type contextType)
: this(Check.NotNull(contextType, "contextType"), null, AppConfig.DefaultInstance, null)
{
}
/// <summary>
/// Creates a new instance representing a given <see cref="DbContext" /> targeting a specific database.
/// </summary>
/// <param name="contextType">
/// The type deriving from <see cref="DbContext" /> .
/// </param>
/// <param name="connectionInfo"> Connection information for the database to be used. </param>
public DbContextInfo(Type contextType, DbConnectionInfo connectionInfo)
: this(
Check.NotNull(contextType, "contextType"), null, AppConfig.DefaultInstance, Check.NotNull(connectionInfo, "connectionInfo"))
{
}
/// <summary>
/// Creates a new instance representing a given <see cref="DbContext" /> type. An external list of
/// connection strings can be supplied and will be used during connection string resolution in place
/// of any connection strings specified in external configuration files.
/// </summary>
/// <remarks>
/// It is preferable to use the constructor that accepts the entire config document instead of using this
/// constructor. Providing the entire config document allows DefaultConnectionFactroy entries in the config
/// to be found in addition to explicitly specified connection strings.
/// </remarks>
/// <param name="contextType">
/// The type deriving from <see cref="DbContext" /> .
/// </param>
/// <param name="connectionStringSettings"> A collection of connection strings. </param>
[Obsolete(
@"The application configuration can contain multiple settings that affect the connection used by a DbContext. To ensure all configuration is taken into account, use a DbContextInfo constructor that accepts System.Configuration.Configuration"
)]
public DbContextInfo(Type contextType, ConnectionStringSettingsCollection connectionStringSettings)
: this(
Check.NotNull(contextType, "contextType"), null,
new AppConfig(Check.NotNull(connectionStringSettings, "connectionStringSettings")), null)
{
}
/// <summary>
/// Creates a new instance representing a given <see cref="DbContext" /> type. An external config
/// object (e.g. app.config or web.config) can be supplied and will be used during connection string
/// resolution. This includes looking for connection strings and DefaultConnectionFactory entries.
/// </summary>
/// <param name="contextType">
/// The type deriving from <see cref="DbContext" /> .
/// </param>
/// <param name="config"> An object representing the config file. </param>
public DbContextInfo(Type contextType, Configuration config)
: this(Check.NotNull(contextType, "contextType"), null, new AppConfig(Check.NotNull(config, "config")), null)
{
}
/// <summary>
/// Creates a new instance representing a given <see cref="DbContext" />, targeting a specific database.
/// An external config object (e.g. app.config or web.config) can be supplied and will be used during connection string
/// resolution. This includes looking for connection strings and DefaultConnectionFactory entries.
/// </summary>
/// <param name="contextType">
/// The type deriving from <see cref="DbContext" /> .
/// </param>
/// <param name="config"> An object representing the config file. </param>
/// <param name="connectionInfo"> Connection information for the database to be used. </param>
public DbContextInfo(Type contextType, Configuration config, DbConnectionInfo connectionInfo)
: this(
Check.NotNull(contextType, "contextType"), null, new AppConfig(Check.NotNull(config, "config")),
Check.NotNull(connectionInfo, "connectionInfo"))
{
}
/// <summary>
/// Creates a new instance representing a given <see cref="DbContext" /> type. A <see cref="DbProviderInfo" />
/// can be supplied in order to override the default determined provider used when constructing
/// the underlying EDM model.
/// </summary>
/// <param name="contextType">
/// The type deriving from <see cref="DbContext" /> .
/// </param>
/// <param name="modelProviderInfo">
/// A <see cref="DbProviderInfo" /> specifying the underlying ADO.NET provider to target.
/// </param>
public DbContextInfo(Type contextType, DbProviderInfo modelProviderInfo)
: this(
Check.NotNull(contextType, "contextType"), Check.NotNull(modelProviderInfo, "modelProviderInfo"), AppConfig.DefaultInstance,
null)
{
}
/// <summary>
/// Creates a new instance representing a given <see cref="DbContext" /> type. An external config
/// object (e.g. app.config or web.config) can be supplied and will be used during connection string
/// resolution. This includes looking for connection strings and DefaultConnectionFactory entries.
/// A <see cref="DbProviderInfo" /> can be supplied in order to override the default determined
/// provider used when constructing the underlying EDM model. This can be useful to prevent EF from
/// connecting to discover a manifest token.
/// </summary>
/// <param name="contextType">
/// The type deriving from <see cref="DbContext" /> .
/// </param>
/// <param name="config"> An object representing the config file. </param>
/// <param name="modelProviderInfo">
/// A <see cref="DbProviderInfo" /> specifying the underlying ADO.NET provider to target.
/// </param>
public DbContextInfo(Type contextType, Configuration config, DbProviderInfo modelProviderInfo)
: this(
Check.NotNull(contextType, "contextType"), Check.NotNull(modelProviderInfo, "modelProviderInfo"),
new AppConfig(Check.NotNull(config, "config")), null)
{
}
/// <summary>
/// Called internally when a context info is needed for an existing context, which may not be constructable.
/// </summary>
/// <param name="context"> The context instance to get info from. </param>
internal DbContextInfo(DbContext context)
{
Check.NotNull(context, "context");
_contextType = context.GetType();
_appConfig = AppConfig.DefaultInstance;
var internalContext = context.InternalContext;
_connectionProviderName = internalContext.ProviderName;
_connectionInfo = new DbConnectionInfo(internalContext.OriginalConnectionString, _connectionProviderName);
_connectionString = internalContext.OriginalConnectionString;
_connectionStringName = internalContext.ConnectionStringName;
_connectionStringOrigin = internalContext.ConnectionStringOrigin;
}
private DbContextInfo(
Type contextType,
DbProviderInfo modelProviderInfo,
AppConfig config,
DbConnectionInfo connectionInfo)
{
if (!typeof(DbContext).IsAssignableFrom(contextType))
{
throw new ArgumentOutOfRangeException("contextType");
}
_contextType = contextType;
_modelProviderInfo = modelProviderInfo;
_appConfig = config;
_connectionInfo = connectionInfo;
_activator = CreateActivator();
if (_activator != null)
{
var context = _activator();
if (context != null)
{
_isConstructible = true;
PushConfiguration(context);
using (context)
{
ConfigureContext(context);
_connectionString = context.InternalContext.Connection.ConnectionString;
_connectionStringName = context.InternalContext.ConnectionStringName;
_connectionProviderName = context.InternalContext.ProviderName;
_connectionStringOrigin = context.InternalContext.ConnectionStringOrigin;
}
}
}
}
private void PushConfiguration(DbContext context)
{
DbConfigurationManager.Instance.PushConfiguration(_appConfig, _contextType);
context.InternalContext.OnDisposing +=
(_, __) => DbConfigurationManager.Instance.PopConfiguration(_appConfig);
}
/// <summary>
/// The concrete <see cref="DbContext" /> type.
/// </summary>
public virtual Type ContextType
{
get { return _contextType; }
}
/// <summary>
/// Whether or not instances of the underlying <see cref="DbContext" /> type can be created.
/// </summary>
public virtual bool IsConstructible
{
get { return _isConstructible; }
}
/// <summary>
/// The connection string used by the underlying <see cref="DbContext" /> type.
/// </summary>
public virtual string ConnectionString
{
get { return _connectionString; }
}
/// <summary>
/// The connection string name used by the underlying <see cref="DbContext" /> type.
/// </summary>
public virtual string ConnectionStringName
{
get { return _connectionStringName; }
}
/// <summary>
/// The ADO.NET provider name of the connection used by the underlying <see cref="DbContext" /> type.
/// </summary>
public virtual string ConnectionProviderName
{
get { return _connectionProviderName; }
}
/// <summary>
/// The origin of the connection string used by the underlying <see cref="DbContext" /> type.
/// </summary>
public virtual DbConnectionStringOrigin ConnectionStringOrigin
{
get { return _connectionStringOrigin; }
}
/// <summary>
/// An action to be run on the DbModelBuilder after OnModelCreating has been run on the context.
/// </summary>
public virtual Action<DbModelBuilder> OnModelCreating
{
get { return _onModelCreating; }
set { _onModelCreating = value; }
}
/// <summary>
/// If instances of the underlying <see cref="DbContext" /> type can be created, returns
/// a new instance; otherwise returns null.
/// </summary>
/// <returns>
/// A <see cref="DbContext" /> instance.
/// </returns>
public virtual DbContext CreateInstance()
{
if (!IsConstructible)
{
return null;
}
var context = _activator();
PushConfiguration(context);
ConfigureContext(context);
return context;
}
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
private void ConfigureContext(DbContext context)
{
DebugCheck.NotNull(context);
if (_modelProviderInfo != null)
{
context.InternalContext.ModelProviderInfo = _modelProviderInfo;
}
context.InternalContext.AppConfig = _appConfig;
if (_connectionInfo != null)
{
context.InternalContext.OverrideConnection(new LazyInternalConnection(_connectionInfo));
}
if (_onModelCreating != null)
{
context.InternalContext.OnModelCreating = _onModelCreating;
}
}
private Func<DbContext> CreateActivator()
{
var constructor = _contextType.GetConstructor(Type.EmptyTypes);
if (constructor != null)
{
return () => (DbContext)Activator.CreateInstance(_contextType);
}
var factoryType
= (from t in _contextType.Assembly.GetAccessibleTypes()
where t.IsClass && typeof(IDbContextFactory<>).MakeGenericType(_contextType).IsAssignableFrom(t)
select t).FirstOrDefault();
if (factoryType == null)
{
return null;
}
if (factoryType.GetConstructor(Type.EmptyTypes) == null)
{
throw Error.DbContextServices_MissingDefaultCtor(factoryType);
}
var factory = (IDbContextFactory<DbContext>)Activator.CreateInstance(factoryType);
return factory.Create;
}
}
}

View File

@@ -0,0 +1,349 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Data.Entity.Utilities;
using System.Data.Entity.Validation;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// A non-generic version of the <see cref="DbEntityEntry{T}" /> class.
/// </summary>
public class DbEntityEntry
{
#region Fields and constructors
private readonly InternalEntityEntry _internalEntityEntry;
/// <summary>
/// Initializes a new instance of the <see cref="DbEntityEntry" /> class.
/// </summary>
/// <param name="internalEntityEntry"> The internal entry. </param>
internal DbEntityEntry(InternalEntityEntry internalEntityEntry)
{
DebugCheck.NotNull(internalEntityEntry);
_internalEntityEntry = internalEntityEntry;
}
#endregion
#region Entity access
/// <summary>
/// Gets the entity.
/// </summary>
/// <value> The entity. </value>
public object Entity
{
get { return _internalEntityEntry.Entity; }
}
#endregion
#region Entity state
/// <summary>
/// Gets or sets the state of the entity.
/// </summary>
/// <value> The state. </value>
public EntityState State
{
get { return _internalEntityEntry.State; }
set { _internalEntityEntry.State = value; }
}
#endregion
#region Property values and concurrency
/// <summary>
/// Gets the current property values for the tracked entity represented by this object.
/// </summary>
/// <value> The current values. </value>
public DbPropertyValues CurrentValues
{
get { return new DbPropertyValues(_internalEntityEntry.CurrentValues); }
}
/// <summary>
/// Gets the original property values for the tracked entity represented by this object.
/// The original values are usually the entity's property values as they were when last queried from
/// the database.
/// </summary>
/// <value> The original values. </value>
public DbPropertyValues OriginalValues
{
get { return new DbPropertyValues(_internalEntityEntry.OriginalValues); }
}
/// <summary>
/// Queries the database for copies of the values of the tracked entity as they currently exist in the database.
/// Note that changing the values in the returned dictionary will not update the values in the database.
/// If the entity is not found in the database then null is returned.
/// </summary>
/// <returns> The store values. </returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public DbPropertyValues GetDatabaseValues()
{
var storeValues = _internalEntityEntry.GetDatabaseValues();
return storeValues == null ? null : new DbPropertyValues(storeValues);
}
#if !NET40
/// <summary>
/// An asynchronous version of GetDatabaseValues, which
/// queries the database for copies of the values of the tracked entity as they currently exist in the database.
/// Note that changing the values in the returned dictionary will not update the values in the database.
/// If the entity is not found in the database then null is returned.
/// </summary>
/// <returns> A Task that contains the store values. </returns>
public Task<DbPropertyValues> GetDatabaseValuesAsync()
{
return GetDatabaseValuesAsync(CancellationToken.None);
}
/// <summary>
/// An asynchronous version of GetDatabaseValues, which
/// queries the database for copies of the values of the tracked entity as they currently exist in the database.
/// Note that changing the values in the returned dictionary will not update the values in the database.
/// If the entity is not found in the database then null is returned.
/// </summary>
/// <param name="cancellationToken"> The token to monitor for cancellation requests. </param>
/// <returns> A Task that contains the store values. </returns>
public async Task<DbPropertyValues> GetDatabaseValuesAsync(CancellationToken cancellationToken)
{
var storeValues =
await _internalEntityEntry.GetDatabaseValuesAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
return storeValues == null ? null : new DbPropertyValues(storeValues);
}
#endif
/// <summary>
/// Reloads the entity from the database overwriting any property values with values from the database.
/// The entity will be in the Unchanged state after calling this method.
/// </summary>
public void Reload()
{
_internalEntityEntry.Reload();
}
#endregion
#region Property, Reference, and Collection fluents
/// <summary>
/// Gets an object that represents the reference (i.e. non-collection) navigation property from this
/// entity to another entity.
/// </summary>
/// <param name="navigationProperty"> The name of the navigation property. </param>
/// <returns> An object representing the navigation property. </returns>
public DbReferenceEntry Reference(string navigationProperty)
{
Check.NotEmpty(navigationProperty, "navigationProperty");
return DbReferenceEntry.Create(_internalEntityEntry.Reference(navigationProperty));
}
/// <summary>
/// Gets an object that represents the collection navigation property from this
/// entity to a collection of related entities.
/// </summary>
/// <param name="navigationProperty"> The name of the navigation property. </param>
/// <returns> An object representing the navigation property. </returns>
public DbCollectionEntry Collection(string navigationProperty)
{
Check.NotEmpty(navigationProperty, "navigationProperty");
return DbCollectionEntry.Create(_internalEntityEntry.Collection(navigationProperty));
}
/// <summary>
/// Gets an object that represents a scalar or complex property of this entity.
/// </summary>
/// <param name="propertyName"> The name of the property. </param>
/// <returns> An object representing the property. </returns>
public DbPropertyEntry Property(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return DbPropertyEntry.Create(_internalEntityEntry.Property(propertyName));
}
/// <summary>
/// Gets an object that represents a complex property of this entity.
/// </summary>
/// <param name="propertyName"> The name of the complex property. </param>
/// <returns> An object representing the complex property. </returns>
public DbComplexPropertyEntry ComplexProperty(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return DbComplexPropertyEntry.Create(
_internalEntityEntry.Property(propertyName, null, requireComplex: true));
}
/// <summary>
/// Gets an object that represents a member of the entity. The runtime type of the returned object will
/// vary depending on what kind of member is asked for. The currently supported member types and their return
/// types are:
/// Reference navigation property: <see cref="DbReferenceEntry" />.
/// Collection navigation property: <see cref="DbCollectionEntry" />.
/// Primitive/scalar property: <see cref="DbPropertyEntry" />.
/// Complex property: <see cref="DbComplexPropertyEntry" />.
/// </summary>
/// <param name="propertyName"> The name of the member. </param>
/// <returns> An object representing the member. </returns>
public DbMemberEntry Member(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return DbMemberEntry.Create(_internalEntityEntry.Member(propertyName));
}
#endregion
#region Conversion to generic
/// <summary>
/// Returns a new instance of the generic <see cref="DbEntityEntry{T}" /> class for the given
/// generic type for the tracked entity represented by this object.
/// Note that the type of the tracked entity must be compatible with the generic type or
/// an exception will be thrown.
/// </summary>
/// <typeparam name="TEntity"> The type of the entity. </typeparam>
/// <returns> A generic version. </returns>
public DbEntityEntry<TEntity> Cast<TEntity>() where TEntity : class
{
if (!typeof(TEntity).IsAssignableFrom(_internalEntityEntry.EntityType))
{
throw Error.DbEntity_BadTypeForCast(
typeof(DbEntityEntry).Name, typeof(TEntity).Name, _internalEntityEntry.EntityType.Name);
}
return new DbEntityEntry<TEntity>(_internalEntityEntry);
}
#endregion
#region Validation
/// <summary>
/// Validates this <see cref="DbEntityEntry" /> instance and returns validation result.
/// </summary>
/// <returns>
/// Entity validation result. Possibly null if
/// <see
/// cref="DbContext.ValidateEntity(DbEntityEntry, IDictionary{object,object})" />
/// method is overridden.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public DbEntityValidationResult GetValidationResult()
{
// need to call the method on DbContext to pickup validation
// customizations the user potentially implemented
return _internalEntityEntry.InternalContext.Owner.CallValidateEntity(this);
}
#endregion
#region InternalEntityEntry access
/// <summary>
/// Gets InternalEntityEntry object for this DbEntityEntry instance.
/// </summary>
internal InternalEntityEntry InternalEntry
{
get { return _internalEntityEntry; }
}
#endregion
#region Equals\GetHashCode implementation
/// <summary>
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
/// Two <see cref="DbEntityEntry" /> instances are considered equal if they are both entries for
/// the same entity on the same <see cref="DbContext" />.
/// </summary>
/// <param name="obj">
/// The <see cref="System.Object" /> to compare with this instance.
/// </param>
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c> .
/// </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
// Still hide it since it is generally not useful to see when dotting in the API.
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)
|| obj.GetType() != typeof(DbEntityEntry))
{
return false;
}
return Equals((DbEntityEntry)obj);
}
/// <summary>
/// Determines whether the specified <see cref="DbEntityEntry" /> is equal to this instance.
/// Two <see cref="DbEntityEntry" /> instances are considered equal if they are both entries for
/// the same entity on the same <see cref="DbContext" />.
/// </summary>
/// <param name="other">
/// The <see cref="DbEntityEntry" /> to compare with this instance.
/// </param>
/// <returns>
/// <c>true</c> if the specified <see cref="DbEntityEntry" /> is equal to this instance; otherwise, <c>false</c> .
/// </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
// Still hide it since it is generally not useful to see when dotting in the API.
public bool Equals(DbEntityEntry other)
{
if (ReferenceEquals(this, other))
{
return true;
}
return !ReferenceEquals(null, other) && _internalEntityEntry.Equals(other._internalEntityEntry);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns> A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
// Still hide it since it is generally not useful to see when dotting in the API.
public override int GetHashCode()
{
return _internalEntityEntry.GetHashCode();
}
#endregion
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{
return base.ToString();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
}
}

View File

@@ -0,0 +1,489 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity.Internal;
using System.Data.Entity.Utilities;
using System.Data.Entity.Validation;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Instances of this class provide access to information about and control of entities that
/// are being tracked by the <see cref="DbContext" />. Use the Entity or Entities methods of
/// the context to obtain objects of this type.
/// </summary>
/// <typeparam name="TEntity"> The type of the entity. </typeparam>
public class DbEntityEntry<TEntity>
where TEntity : class
{
#region Fields and constructors
private readonly InternalEntityEntry _internalEntityEntry;
/// <summary>
/// Initializes a new instance of the <see cref="DbEntityEntry{TEntity}" /> class.
/// </summary>
/// <param name="internalEntityEntry"> The internal entry. </param>
internal DbEntityEntry(InternalEntityEntry internalEntityEntry)
{
DebugCheck.NotNull(internalEntityEntry);
_internalEntityEntry = internalEntityEntry;
}
#endregion
#region Entity access
/// <summary>
/// Gets the entity.
/// </summary>
/// <value> The entity. </value>
public TEntity Entity
{
get { return (TEntity)_internalEntityEntry.Entity; }
}
#endregion
#region Entity state
/// <summary>
/// Gets or sets the state of the entity.
/// </summary>
/// <value> The state. </value>
public EntityState State
{
get { return _internalEntityEntry.State; }
set { _internalEntityEntry.State = value; }
}
#endregion
#region Property values and concurrency
/// <summary>
/// Gets the current property values for the tracked entity represented by this object.
/// </summary>
/// <value> The current values. </value>
public DbPropertyValues CurrentValues
{
get { return new DbPropertyValues(_internalEntityEntry.CurrentValues); }
}
/// <summary>
/// Gets the original property values for the tracked entity represented by this object.
/// The original values are usually the entity's property values as they were when last queried from
/// the database.
/// </summary>
/// <value> The original values. </value>
public DbPropertyValues OriginalValues
{
get { return new DbPropertyValues(_internalEntityEntry.OriginalValues); }
}
/// <summary>
/// Queries the database for copies of the values of the tracked entity as they currently exist in the database.
/// Note that changing the values in the returned dictionary will not update the values in the database.
/// If the entity is not found in the database then null is returned.
/// </summary>
/// <returns> The store values. </returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public DbPropertyValues GetDatabaseValues()
{
var storeValues = _internalEntityEntry.GetDatabaseValues();
return storeValues == null ? null : new DbPropertyValues(storeValues);
}
#if !NET40
/// <summary>
/// An asynchronous version of GetDatabaseValues, which
/// queries the database for copies of the values of the tracked entity as they currently exist in the database.
/// Note that changing the values in the returned dictionary will not update the values in the database.
/// If the entity is not found in the database then null is returned.
/// </summary>
/// <returns> A Task that contains the store values. </returns>
public Task<DbPropertyValues> GetDatabaseValuesAsync()
{
return GetDatabaseValuesAsync(CancellationToken.None);
}
/// <summary>
/// An asynchronous version of GetDatabaseValues, which
/// queries the database for copies of the values of the tracked entity as they currently exist in the database.
/// Note that changing the values in the returned dictionary will not update the values in the database.
/// If the entity is not found in the database then null is returned.
/// </summary>
/// <param name="cancellationToken"> The token to monitor for cancellation requests. </param>
/// <returns> A Task that contains the store values. </returns>
public async Task<DbPropertyValues> GetDatabaseValuesAsync(CancellationToken cancellationToken)
{
var storeValues =
await _internalEntityEntry.GetDatabaseValuesAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
return storeValues == null ? null : new DbPropertyValues(storeValues);
}
#endif
/// <summary>
/// Reloads the entity from the database overwriting any property values with values from the database.
/// The entity will be in the Unchanged state after calling this method.
/// </summary>
public void Reload()
{
_internalEntityEntry.Reload();
}
#endregion
#region Property, Reference, and Collection fluents
/// <summary>
/// Gets an object that represents the reference (i.e. non-collection) navigation property from this
/// entity to another entity.
/// </summary>
/// <param name="navigationProperty"> The name of the navigation property. </param>
/// <returns> An object representing the navigation property. </returns>
public DbReferenceEntry Reference(string navigationProperty)
{
Check.NotEmpty(navigationProperty, "navigationProperty");
return DbReferenceEntry.Create(_internalEntityEntry.Reference(navigationProperty));
}
/// <summary>
/// Gets an object that represents the reference (i.e. non-collection) navigation property from this
/// entity to another entity.
/// </summary>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
/// <param name="navigationProperty"> The name of the navigation property. </param>
/// <returns> An object representing the navigation property. </returns>
public DbReferenceEntry<TEntity, TProperty> Reference<TProperty>(string navigationProperty)
where TProperty : class
{
Check.NotEmpty(navigationProperty, "navigationProperty");
return
DbReferenceEntry<TEntity, TProperty>.Create(
_internalEntityEntry.Reference(navigationProperty, typeof(TProperty)));
}
/// <summary>
/// Gets an object that represents the reference (i.e. non-collection) navigation property from this
/// entity to another entity.
/// </summary>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
/// <param name="navigationProperty"> An expression representing the navigation property. </param>
/// <returns> An object representing the navigation property. </returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
public DbReferenceEntry<TEntity, TProperty> Reference<TProperty>(
Expression<Func<TEntity, TProperty>> navigationProperty)
where TProperty : class
{
Check.NotNull(navigationProperty, "navigationProperty");
return
DbReferenceEntry<TEntity, TProperty>.Create(
_internalEntityEntry.Reference(
DbHelpers.ParsePropertySelector(navigationProperty, "Reference", "navigationProperty"),
typeof(TProperty)));
}
/// <summary>
/// Gets an object that represents the collection navigation property from this
/// entity to a collection of related entities.
/// </summary>
/// <param name="navigationProperty"> The name of the navigation property. </param>
/// <returns> An object representing the navigation property. </returns>
public DbCollectionEntry Collection(string navigationProperty)
{
Check.NotEmpty(navigationProperty, "navigationProperty");
return DbCollectionEntry.Create(_internalEntityEntry.Collection(navigationProperty));
}
/// <summary>
/// Gets an object that represents the collection navigation property from this
/// entity to a collection of related entities.
/// </summary>
/// <typeparam name="TElement"> The type of elements in the collection. </typeparam>
/// <param name="navigationProperty"> The name of the navigation property. </param>
/// <returns> An object representing the navigation property. </returns>
public DbCollectionEntry<TEntity, TElement> Collection<TElement>(string navigationProperty)
where TElement : class
{
Check.NotEmpty(navigationProperty, "navigationProperty");
return
DbCollectionEntry<TEntity, TElement>.Create(
_internalEntityEntry.Collection(navigationProperty, typeof(TElement)));
}
/// <summary>
/// Gets an object that represents the collection navigation property from this
/// entity to a collection of related entities.
/// </summary>
/// <typeparam name="TElement"> The type of elements in the collection. </typeparam>
/// <param name="navigationProperty"> An expression representing the navigation property. </param>
/// <returns> An object representing the navigation property. </returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
public DbCollectionEntry<TEntity, TElement> Collection<TElement>(
Expression<Func<TEntity, ICollection<TElement>>> navigationProperty) where TElement : class
{
Check.NotNull(navigationProperty, "navigationProperty");
return
Collection<TElement>(
DbHelpers.ParsePropertySelector(navigationProperty, "Collection", "navigationProperty"));
}
/// <summary>
/// Gets an object that represents a scalar or complex property of this entity.
/// </summary>
/// <param name="propertyName"> The name of the property. </param>
/// <returns> An object representing the property. </returns>
public DbPropertyEntry Property(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return DbPropertyEntry.Create(_internalEntityEntry.Property(propertyName));
}
/// <summary>
/// Gets an object that represents a scalar or complex property of this entity.
/// </summary>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
/// <param name="propertyName"> The name of the property. </param>
/// <returns> An object representing the property. </returns>
public DbPropertyEntry<TEntity, TProperty> Property<TProperty>(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return
DbPropertyEntry<TEntity, TProperty>.Create(
_internalEntityEntry.Property(propertyName, typeof(TProperty)));
}
/// <summary>
/// Gets an object that represents a scalar or complex property of this entity.
/// </summary>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
/// <param name="navigationProperty"> An expression representing the property. </param>
/// <returns> An object representing the property. </returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
[SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#",
Justification = "Rule predates more fluent naming conventions.")]
public DbPropertyEntry<TEntity, TProperty> Property<TProperty>(Expression<Func<TEntity, TProperty>> property)
{
Check.NotNull(property, "property");
return Property<TProperty>(DbHelpers.ParsePropertySelector(property, "Property", "property"));
}
/// <summary>
/// Gets an object that represents a complex property of this entity.
/// </summary>
/// <param name="propertyName"> The name of the complex property. </param>
/// <returns> An object representing the complex property. </returns>
public DbComplexPropertyEntry ComplexProperty(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return DbComplexPropertyEntry.Create(
_internalEntityEntry.Property(propertyName, null, requireComplex: true));
}
/// <summary>
/// Gets an object that represents a complex property of this entity.
/// </summary>
/// <typeparam name="TComplexProperty"> The type of the complex property. </typeparam>
/// <param name="propertyName"> The name of the complex property. </param>
/// <returns> An object representing the complex property. </returns>
public DbComplexPropertyEntry<TEntity, TComplexProperty> ComplexProperty<TComplexProperty>(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return
DbComplexPropertyEntry<TEntity, TComplexProperty>.Create(
_internalEntityEntry.Property(propertyName, typeof(TComplexProperty), requireComplex: true));
}
/// <summary>
/// Gets an object that represents a complex property of this entity.
/// </summary>
/// <typeparam name="TComplexProperty"> The type of the complex property. </typeparam>
/// <param name="navigationProperty"> An expression representing the complex property. </param>
/// <returns> An object representing the complex property. </returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
[SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#",
Justification = "Rule predates more fluent naming conventions.")]
public DbComplexPropertyEntry<TEntity, TComplexProperty> ComplexProperty<TComplexProperty>(
Expression<Func<TEntity, TComplexProperty>> property)
{
Check.NotNull(property, "property");
return ComplexProperty<TComplexProperty>(DbHelpers.ParsePropertySelector(property, "Property", "property"));
}
/// <summary>
/// Gets an object that represents a member of the entity. The runtime type of the returned object will
/// vary depending on what kind of member is asked for. The currently supported member types and their return
/// types are:
/// Reference navigation property: <see cref="DbReferenceEntry" />.
/// Collection navigation property: <see cref="DbCollectionEntry" />.
/// Primitive/scalar property: <see cref="DbPropertyEntry" />.
/// Complex property: <see cref="DbComplexPropertyEntry" />.
/// </summary>
/// <param name="propertyName"> The name of the member. </param>
/// <returns> An object representing the member. </returns>
public DbMemberEntry Member(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return DbMemberEntry.Create(_internalEntityEntry.Member(propertyName));
}
/// <summary>
/// Gets an object that represents a member of the entity. The runtime type of the returned object will
/// vary depending on what kind of member is asked for. The currently supported member types and their return
/// types are:
/// Reference navigation property: <see cref="DbReferenceEntry{TEntity, TProperty}" />.
/// Collection navigation property: <see cref="DbCollectionEntry{TEntity, TElement}" />.
/// Primitive/scalar property: <see cref="DbPropertyEntry{TEntity, TProperty}" />.
/// Complex property: <see cref="DbComplexPropertyEntry{TEntity, TProperty}" />.
/// </summary>
/// <typeparam name="TMember"> The type of the member. </typeparam>
/// <param name="propertyName"> The name of the member. </param>
/// <returns> An object representing the member. </returns>
public DbMemberEntry<TEntity, TMember> Member<TMember>(string propertyName)
{
Check.NotEmpty(propertyName, "propertyName");
return _internalEntityEntry.Member(propertyName, typeof(TMember)).CreateDbMemberEntry<TEntity, TMember>();
}
#endregion
#region Conversion to non-generic
/// <summary>
/// Returns a new instance of the non-generic <see cref="DbEntityEntry" /> class for
/// the tracked entity represented by this object.
/// </summary>
/// <returns> A non-generic version. </returns>
[SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",
Justification = "Intentionally just implicit to reduce API clutter.")]
public static implicit operator DbEntityEntry(DbEntityEntry<TEntity> entry)
{
return new DbEntityEntry(entry._internalEntityEntry);
}
#endregion
#region Validation
/// <summary>
/// Validates this <see cref="DbEntityEntry{T}" /> instance and returns validation result.
/// </summary>
/// <returns>
/// Entity validation result. Possibly null if
/// <see
/// cref="DbContext.ValidateEntity(DbEntityEntry, IDictionary{object, object})" />
/// method is overridden.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public DbEntityValidationResult GetValidationResult()
{
// need to call the method on DbContext to pickup potential validation
// customizations the user potentially implemented
return _internalEntityEntry.InternalContext.Owner.CallValidateEntity(this);
}
#endregion
#region Equals\GetHashCode implementation
/// <summary>
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
/// Two <see cref="DbEntityEntry{TEntity}" /> instances are considered equal if they are both entries for
/// the same entity on the same <see cref="DbContext" />.
/// </summary>
/// <param name="obj">
/// The <see cref="System.Object" /> to compare with this instance.
/// </param>
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c> .
/// </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
// Still hide it since it is generally not useful to see when dotting in the API.
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)
|| obj.GetType() != typeof(DbEntityEntry<TEntity>))
{
return false;
}
return Equals((DbEntityEntry<TEntity>)obj);
}
/// <summary>
/// Determines whether the specified <see cref="DbEntityEntry{TEntity}" /> is equal to this instance.
/// Two <see cref="DbEntityEntry{TEntity}" /> instances are considered equal if they are both entries for
/// the same entity on the same <see cref="DbContext" />.
/// </summary>
/// <param name="other">
/// The <see cref="DbEntityEntry{TEntity}" /> to compare with this instance.
/// </param>
/// <returns>
/// <c>true</c> if the specified <see cref="DbEntityEntry{TEntity}" /> is equal to this instance; otherwise, <c>false</c> .
/// </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
// Still hide it since it is generally not useful to see when dotting in the API.
public bool Equals(DbEntityEntry<TEntity> other)
{
if (ReferenceEquals(this, other))
{
return true;
}
return !ReferenceEquals(null, other) && _internalEntityEntry.Equals(other._internalEntityEntry);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns> A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
// Still hide it since it is generally not useful to see when dotting in the API.
public override int GetHashCode()
{
return _internalEntityEntry.GetHashCode();
}
#endregion
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{
return base.ToString();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
}
}

View File

@@ -0,0 +1,152 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Data.Entity.Utilities;
using System.Data.Entity.Validation;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
/// <summary>
/// This is an abstract base class use to represent a scalar or complex property, or a navigation property
/// of an entity. Scalar and complex properties use the derived class <see cref="DbPropertyEntry" />,
/// reference navigation properties use the derived class <see cref="DbReferenceEntry" />, and collection
/// navigation properties use the derived class <see cref="DbCollectionEntry" />.
/// </summary>
public abstract class DbMemberEntry
{
#region Factory methods
/// <summary>
/// Creates a <see cref="DbMemberEntry" /> from information in the given <see cref="InternalMemberEntry" />.
/// This method will create an instance of the appropriate subclass depending on the metadata contained
/// in the InternalMemberEntry instance.
/// </summary>
/// <param name="internalMemberEntry"> The internal member entry. </param>
/// <returns> The new entry. </returns>
internal static DbMemberEntry Create(InternalMemberEntry internalMemberEntry)
{
DebugCheck.NotNull(internalMemberEntry);
return internalMemberEntry.CreateDbMemberEntry();
}
#endregion
#region Name
/// <summary>
/// Gets the name of the property.
/// </summary>
/// <value> The property name. </value>
public abstract string Name { get; }
#endregion
#region Current values
/// <summary>
/// Gets or sets the current value of this property.
/// </summary>
/// <value> The current value. </value>
public abstract object CurrentValue { get; set; }
#endregion
#region Back references
/// <summary>
/// The <see cref="DbEntityEntry" /> to which this member belongs.
/// </summary>
/// <value> An entry for the entity that owns this member. </value>
public abstract DbEntityEntry EntityEntry { get; }
#endregion
#region Validation
/// <summary>
/// Validates this property.
/// </summary>
/// <returns>
/// Collection of <see cref="DbValidationError" /> objects. Never null. If the entity is valid the collection will be empty.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public ICollection<DbValidationError> GetValidationErrors()
{
return InternalMemberEntry.GetValidationErrors().ToList();
}
#endregion
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{
return base.ToString();
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return base.GetHashCode();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
#region InternalMemberEntry access
/// <summary>
/// Gets the <see cref="InternalMemberEntry" /> backing this object.
/// </summary>
/// <value> The internal member entry. </value>
internal abstract InternalMemberEntry InternalMemberEntry { get; }
#endregion
#region Conversion to generic
/// <summary>
/// Returns the equivalent generic <see cref="DbMemberEntry{TEntity,TProperty}" /> object.
/// </summary>
/// <typeparam name="TEntity"> The type of entity on which the member is declared. </typeparam>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
/// <returns> The equivalent generic object. </returns>
public DbMemberEntry<TEntity, TProperty> Cast<TEntity, TProperty>() where TEntity : class
{
var metadata = InternalMemberEntry.EntryMetadata;
if (!typeof(TEntity).IsAssignableFrom(metadata.DeclaringType)
|| !typeof(TProperty).IsAssignableFrom(metadata.MemberType))
{
throw Error.DbMember_BadTypeForCast(
typeof(DbMemberEntry).Name,
typeof(TEntity).Name,
typeof(TProperty).Name,
metadata.DeclaringType.Name,
metadata.MemberType.Name);
}
return DbMemberEntry<TEntity, TProperty>.Create(InternalMemberEntry);
}
#endregion
}
}

View File

@@ -0,0 +1,142 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity.Internal;
using System.Data.Entity.Utilities;
using System.Data.Entity.Validation;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
/// <summary>
/// This is an abstract base class use to represent a scalar or complex property, or a navigation property
/// of an entity. Scalar and complex properties use the derived class <see cref="DbPropertyEntry{TEntity, TProperty}" />,
/// reference navigation properties use the derived class <see cref="DbReferenceEntry{TEntity, TProperty}" />, and collection
/// navigation properties use the derived class <see cref="DbCollectionEntry{TEntity, TProperty}" />.
/// </summary>
/// <typeparam name="TEntity"> The type of the entity to which this property belongs. </typeparam>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
public abstract class DbMemberEntry<TEntity, TProperty>
where TEntity : class
{
#region Factory methods
/// <summary>
/// Creates a <see cref="DbMemberEntry{TEntity,TProperty}" /> from information in the given
/// <see
/// cref="InternalMemberEntry" />
/// .
/// This method will create an instance of the appropriate subclass depending on the metadata contained
/// in the InternalMemberEntry instance.
/// </summary>
/// <param name="internalMemberEntry"> The internal member entry. </param>
/// <returns> The new entry. </returns>
internal static DbMemberEntry<TEntity, TProperty> Create(InternalMemberEntry internalMemberEntry)
{
DebugCheck.NotNull(internalMemberEntry);
return internalMemberEntry.CreateDbMemberEntry<TEntity, TProperty>();
}
#endregion
#region Name
public abstract string Name { get; }
#endregion
#region Current values
/// <summary>
/// Gets or sets the current value of this property.
/// </summary>
/// <value> The current value. </value>
public abstract TProperty CurrentValue { get; set; }
#endregion
#region Conversion to non-generic
/// <summary>
/// Returns a new instance of the non-generic <see cref="DbMemberEntry" /> class for
/// the property represented by this object.
/// </summary>
/// <returns> A non-generic version. </returns>
[SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",
Justification = "Intentionally just implicit to reduce API clutter.")]
public static implicit operator DbMemberEntry(DbMemberEntry<TEntity, TProperty> entry)
{
return DbMemberEntry.Create(entry.InternalMemberEntry);
}
#endregion
#region Internal entry access
/// <summary>
/// Gets the underlying <see cref="InternalMemberEntry" />.
/// </summary>
/// <value> The internal member entry. </value>
internal abstract InternalMemberEntry InternalMemberEntry { get; }
#endregion
#region Back references
/// <summary>
/// The <see cref="DbEntityEntry{TEntity}" /> to which this member belongs.
/// </summary>
/// <value> An entry for the entity that owns this member. </value>
public abstract DbEntityEntry<TEntity> EntityEntry { get; }
#endregion
#region Validation
/// <summary>
/// Validates this property.
/// </summary>
/// <returns>
/// Collection of <see cref="DbValidationError" /> objects. Never null. If the entity is valid the collection will be empty.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public ICollection<DbValidationError> GetValidationErrors()
{
return InternalMemberEntry.GetValidationErrors().ToList();
}
#endregion
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{
return base.ToString();
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return base.GetHashCode();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
}
}

View File

@@ -0,0 +1,66 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Utilities;
/// <summary>
/// Represents an Entity Data Model (EDM) created by the <see cref="DbModelBuilder" />.
/// The Compile method can be used to go from this EDM representation to a <see cref="DbCompiledModel" />
/// which is a compiled snapshot of the model suitable for caching and creation of
/// <see cref="DbContext" /> or <see cref="T:System.Data.Objects.ObjectContext" /> instances.
/// </summary>
public class DbModel
{
#region Fields and constructore
private readonly DbDatabaseMapping _databaseMapping;
private readonly DbModelBuilder _cachedModelBuilder;
/// <summary>
/// Initializes a new instance of the <see cref="DbModel" /> class.
/// </summary>
internal DbModel(DbDatabaseMapping databaseMapping, DbModelBuilder modelBuilder)
{
DebugCheck.NotNull(databaseMapping);
DebugCheck.NotNull(modelBuilder);
_databaseMapping = databaseMapping;
_cachedModelBuilder = modelBuilder;
}
#endregion
#region Internal properties
/// <summary>
/// A snapshot of the <see cref="DbModelBuilder" /> that was used to create this compiled model.
/// </summary>
internal DbModelBuilder CachedModelBuilder
{
get { return _cachedModelBuilder; }
}
public DbDatabaseMapping DatabaseMapping
{
get { return _databaseMapping; }
}
#endregion
#region Compile
/// <summary>
/// Creates a <see cref="DbCompiledModel" /> for this mode which is a compiled snapshot
/// suitable for caching and creation of <see cref="DbContext" /> instances.
/// </summary>
/// <returns> The compiled model. </returns>
public DbCompiledModel Compile()
{
return new DbCompiledModel(this);
}
#endregion
}
}

View File

@@ -0,0 +1,170 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Data.Entity.Internal;
using System.Data.Entity.Resources;
using System.Data.Entity.Utilities;
/// <summary>
/// A non-generic version of the <see cref="DbPropertyEntry{TEntity, TProperty}" /> class.
/// </summary>
public class DbPropertyEntry : DbMemberEntry
{
#region Fields and constructors
private readonly InternalPropertyEntry _internalPropertyEntry;
/// <summary>
/// Creates a <see cref="DbPropertyEntry" /> from information in the given <see cref="InternalPropertyEntry" />.
/// Use this method in preference to the constructor since it may potentially create a subclass depending on
/// the type of member represented by the InternalCollectionEntry instance.
/// </summary>
/// <param name="internalPropertyEntry"> The internal property entry. </param>
/// <returns> The new entry. </returns>
internal static DbPropertyEntry Create(InternalPropertyEntry internalPropertyEntry)
{
DebugCheck.NotNull(internalPropertyEntry);
return (DbPropertyEntry)internalPropertyEntry.CreateDbMemberEntry();
}
/// <summary>
/// Initializes a new instance of the <see cref="DbPropertyEntry" /> class.
/// </summary>
/// <param name="internalPropertyEntry"> The internal entry. </param>
internal DbPropertyEntry(InternalPropertyEntry internalPropertyEntry)
{
DebugCheck.NotNull(internalPropertyEntry);
_internalPropertyEntry = internalPropertyEntry;
}
#endregion
#region Name
/// <summary>
/// Gets the property name.
/// </summary>
/// <value> The property name. </value>
public override string Name
{
get { return _internalPropertyEntry.Name; }
}
#endregion
#region Current and Original values
/// <summary>
/// Gets or sets the original value of this property.
/// </summary>
/// <value> The original value. </value>
public object OriginalValue
{
get { return _internalPropertyEntry.OriginalValue; }
set { _internalPropertyEntry.OriginalValue = value; }
}
/// <summary>
/// Gets or sets the current value of this property.
/// </summary>
/// <value> The current value. </value>
public override object CurrentValue
{
get { return _internalPropertyEntry.CurrentValue; }
set { _internalPropertyEntry.CurrentValue = value; }
}
/// <summary>
/// Gets or sets a value indicating whether the value of this property has been modified since
/// it was loaded from the database.
/// </summary>
/// <remarks>
/// Setting this value to false for a modified property will revert the change by setting the
/// current value to the original value. If the result is that no properties of the entity are
/// marked as modified, then the entity will be marked as Unchanged.
/// Setting this value to false for properties of Added, Unchanged, or Deleted entities
/// is a no-op.
/// </remarks>
/// <value>
/// <c>true</c> if this instance is modified; otherwise, <c>false</c> .
/// </value>
public bool IsModified
{
get { return _internalPropertyEntry.IsModified; }
set { _internalPropertyEntry.IsModified = value; }
}
#endregion
#region Back references
/// <summary>
/// The <see cref="DbEntityEntry" /> to which this property belongs.
/// </summary>
/// <value> An entry for the entity that owns this property. </value>
public override DbEntityEntry EntityEntry
{
get { return new DbEntityEntry(_internalPropertyEntry.InternalEntityEntry); }
}
/// <summary>
/// The <see cref="DbPropertyEntry" /> of the property for which this is a nested property.
/// This method will only return a non-null entry for properties of complex objects; it will
/// return null for properties of the entity itself.
/// </summary>
/// <value> An entry for the parent complex property, or null if this is an entity property. </value>
public DbComplexPropertyEntry ParentProperty
{
get
{
var propertyEntry = _internalPropertyEntry.ParentPropertyEntry;
return propertyEntry != null ? DbComplexPropertyEntry.Create(propertyEntry) : null;
}
}
#endregion
#region InternalMemberEntry access
/// <summary>
/// Gets the <see cref="InternalPropertyEntry" /> backing this object.
/// </summary>
/// <value> The internal member entry. </value>
internal override InternalMemberEntry InternalMemberEntry
{
get { return _internalPropertyEntry; }
}
#endregion
#region Conversion to generic
/// <summary>
/// Returns the equivalent generic <see cref="DbPropertyEntry{TEntity,TProperty}" /> object.
/// </summary>
/// <typeparam name="TEntity"> The type of entity on which the member is declared. </typeparam>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
/// <returns> The equivalent generic object. </returns>
public new DbPropertyEntry<TEntity, TProperty> Cast<TEntity, TProperty>() where TEntity : class
{
var metadata = _internalPropertyEntry.EntryMetadata;
if (!typeof(TEntity).IsAssignableFrom(metadata.DeclaringType)
|| !typeof(TProperty).IsAssignableFrom(metadata.ElementType))
{
throw Error.DbMember_BadTypeForCast(
typeof(DbPropertyEntry).Name,
typeof(TEntity).Name,
typeof(TProperty).Name,
metadata.DeclaringType.Name,
metadata.MemberType.Name);
}
return DbPropertyEntry<TEntity, TProperty>.Create(_internalPropertyEntry);
}
#endregion
}
}

View File

@@ -0,0 +1,165 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Data.Entity.Internal;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
/// <summary>
/// Instances of this class are returned from the Property method of
/// <see cref="DbEntityEntry{T}" /> and allow access to the state of the scalar
/// or complex property.
/// </summary>
/// <typeparam name="TEntity"> The type of the entity to which this property belongs. </typeparam>
/// <typeparam name="TProperty"> The type of the property. </typeparam>
public class DbPropertyEntry<TEntity, TProperty> : DbMemberEntry<TEntity, TProperty>
where TEntity : class
{
#region Fields and constructors
private readonly InternalPropertyEntry _internalPropertyEntry;
/// <summary>
/// Creates a <see cref="DbPropertyEntry{TEntity,TProperty}" /> from information in the given
/// <see
/// cref="InternalPropertyEntry" />
/// .
/// Use this method in preference to the constructor since it may potentially create a subclass depending on
/// the type of member represented by the InternalCollectionEntry instance.
/// </summary>
/// <param name="internalPropertyEntry"> The internal property entry. </param>
/// <returns> The new entry. </returns>
internal static DbPropertyEntry<TEntity, TProperty> Create(InternalPropertyEntry internalPropertyEntry)
{
DebugCheck.NotNull(internalPropertyEntry);
return (DbPropertyEntry<TEntity, TProperty>)internalPropertyEntry.CreateDbMemberEntry<TEntity, TProperty>();
}
/// <summary>
/// Initializes a new instance of the <see cref="DbPropertyEntry{TEntity, TProperty}" /> class.
/// </summary>
/// <param name="internalPropertyEntry"> The internal entry. </param>
internal DbPropertyEntry(InternalPropertyEntry internalPropertyEntry)
{
DebugCheck.NotNull(internalPropertyEntry);
_internalPropertyEntry = internalPropertyEntry;
}
#endregion
#region Name
/// <summary>
/// Gets the property name.
/// </summary>
/// <value> The property name. </value>
public override string Name
{
get { return _internalPropertyEntry.Name; }
}
#endregion
#region Current and Original values
/// <summary>
/// Gets or sets the original value of this property.
/// </summary>
/// <value> The original value. </value>
public TProperty OriginalValue
{
get { return (TProperty)_internalPropertyEntry.OriginalValue; }
set { _internalPropertyEntry.OriginalValue = value; }
}
/// <summary>
/// Gets or sets the current value of this property.
/// </summary>
/// <value> The current value. </value>
public override TProperty CurrentValue
{
get { return (TProperty)_internalPropertyEntry.CurrentValue; }
set { _internalPropertyEntry.CurrentValue = value; }
}
/// <summary>
/// Gets or sets a value indicating whether the value of this property has been modified since
/// it was loaded from the database.
/// </summary>
/// <value>
/// <c>true</c> if this instance is modified; otherwise, <c>false</c> .
/// </value>
public bool IsModified
{
get { return _internalPropertyEntry.IsModified; }
set { _internalPropertyEntry.IsModified = value; }
}
#endregion
#region Conversion to non-generic
/// <summary>
/// Returns a new instance of the non-generic <see cref="DbPropertyEntry" /> class for
/// the property represented by this object.
/// </summary>
/// <returns> A non-generic version. </returns>
[SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",
Justification = "Intentionally just implicit to reduce API clutter.")]
public static implicit operator DbPropertyEntry(DbPropertyEntry<TEntity, TProperty> entry)
{
return DbPropertyEntry.Create(entry._internalPropertyEntry);
}
#endregion
#region Back references
/// <summary>
/// The <see cref="DbEntityEntry{TEntity}" /> to which this property belongs.
/// </summary>
/// <value> An entry for the entity that owns this property. </value>
public override DbEntityEntry<TEntity> EntityEntry
{
get { return new DbEntityEntry<TEntity>(_internalPropertyEntry.InternalEntityEntry); }
}
/// <summary>
/// The <see cref="DbPropertyEntry" /> of the property for which this is a nested property.
/// This method will only return a non-null entry for properties of complex objects; it will
/// return null for properties of the entity itself.
/// </summary>
/// <value> An entry for the parent complex property, or null if this is an entity property. </value>
public DbComplexPropertyEntry ParentProperty
{
get
{
var propertyEntry = _internalPropertyEntry.ParentPropertyEntry;
return propertyEntry != null ? DbComplexPropertyEntry.Create(propertyEntry) : null;
}
}
#endregion
#region Internal entry access
internal InternalPropertyEntry InternalPropertyEntry
{
get { return _internalPropertyEntry; }
}
/// <summary>
/// Gets the underlying <see cref="InternalPropertyEntry" /> as an <see cref="InternalMemberEntry" />.
/// </summary>
/// <value> The internal member entry. </value>
internal override InternalMemberEntry InternalMemberEntry
{
get { return InternalPropertyEntry; }
}
#endregion
}
}

View File

@@ -0,0 +1,195 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity.Internal;
using System.Data.Entity.Utilities;
using System.Diagnostics.CodeAnalysis;
/// <summary>
/// A collection of all the properties for an underlying entity or complex object.
/// </summary>
/// <remarks>
/// An instance of this class can be converted to an instance of the generic class
/// using the Cast method.
/// Complex properties in the underlying entity or complex object are represented in
/// the property values as nested instances of this class.
/// </remarks>
public class DbPropertyValues
{
#region Fields and constructors
private readonly InternalPropertyValues _internalValues;
/// <summary>
/// Initializes a new instance of the <see cref="DbPropertyValues" /> class.
/// </summary>
/// <param name="internalValues"> The internal dictionary. </param>
internal DbPropertyValues(InternalPropertyValues internalValues)
{
DebugCheck.NotNull(internalValues);
_internalValues = internalValues;
}
#endregion
#region Copy to and from objects
/// <summary>
/// Creates an object of the underlying type for this dictionary and hydrates it with property
/// values from this dictionary.
/// </summary>
/// <returns> The properties of this dictionary copied into a new object. </returns>
public object ToObject()
{
return _internalValues.ToObject();
}
/// <summary>
/// Sets the values of this dictionary by reading values out of the given object.
/// The given object can be of any type. Any property on the object with a name that
/// matches a property name in the dictionary and can be read will be read. Other
/// properties will be ignored. This allows, for example, copying of properties from
/// simple Data Transfer Objects (DTOs).
/// </summary>
/// <param name="obj"> The object to read values from. </param>
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "obj",
Justification = "Naming is intentional.")]
public void SetValues(object obj)
{
Check.NotNull(obj, "obj");
_internalValues.SetValues(obj);
}
#endregion
#region Copy to and from property values
/// <summary>
/// Creates a new dictionary containing copies of all the properties in this dictionary.
/// Changes made to the new dictionary will not be reflected in this dictionary and vice versa.
/// </summary>
/// <returns> A clone of this dictionary. </returns>
public DbPropertyValues Clone()
{
return new DbPropertyValues(_internalValues.Clone());
}
/// <summary>
/// Sets the values of this dictionary by reading values from another dictionary.
/// The other dictionary must be based on the same type as this dictionary, or a type derived
/// from the type for this dictionary.
/// </summary>
/// <param name="dictionary"> The dictionary to read values from. </param>
public void SetValues(DbPropertyValues propertyValues)
{
Check.NotNull(propertyValues, "propertyValues");
_internalValues.SetValues(propertyValues._internalValues);
}
#endregion
#region Property name/value access
/// <summary>
/// Gets the set of names of all properties in this dictionary as a read-only set.
/// </summary>
/// <value> The property names. </value>
public IEnumerable<string> PropertyNames
{
get { return _internalValues.PropertyNames; }
}
/// <summary>
/// Gets or sets the value of the property with the specified property name.
/// The value may be a nested instance of this class.
/// </summary>
/// <param name="propertyName"> The property name. </param>
/// <value> The value of the property. </value>
public object this[string propertyName]
{
get
{
Check.NotEmpty(propertyName, "propertyName");
var value = _internalValues[propertyName];
var asValues = value as InternalPropertyValues;
if (asValues != null)
{
value = new DbPropertyValues(asValues);
}
return value;
}
set
{
Check.NotEmpty(propertyName, "propertyName");
_internalValues[propertyName] = value;
}
}
/// <summary>
/// Gets the value of the property just like using the indexed property getter but
/// typed to the type of the generic parameter. This is useful especially with
/// nested dictionaries to avoid writing expressions with lots of casts.
/// </summary>
/// <typeparam name="TValue"> The type of the property. </typeparam>
/// <param name="propertyName"> Name of the property. </param>
/// <returns> The value of the property. </returns>
public TValue GetValue<TValue>(string propertyName)
{
return (TValue)this[propertyName];
}
#endregion
#region InternalPropertyValues access
/// <summary>
/// Gets the internal dictionary.
/// </summary>
/// <value> The internal dictionary. </value>
internal InternalPropertyValues InternalPropertyValues
{
get { return _internalValues; }
}
#endregion
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{
return base.ToString();
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return base.GetHashCode();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Data.Entity.Utilities;
public sealed class DbProviderInfo
{
private readonly string _providerInvariantName;
private readonly string _providerManifestToken;
public DbProviderInfo(string providerInvariantName, string providerManifestToken)
{
Check.NotEmpty(providerInvariantName, "providerInvariantName");
Check.NotEmpty(providerManifestToken, "providerManifestToken");
_providerInvariantName = providerInvariantName;
_providerManifestToken = providerManifestToken;
}
public string ProviderInvariantName
{
get { return _providerInvariantName; }
}
public string ProviderManifestToken
{
get { return _providerManifestToken; }
}
}
}

View File

@@ -0,0 +1,253 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Infrastructure
{
using System.Collections;
using System.ComponentModel;
using System.Data.Entity.Internal.Linq;
using System.Data.Entity.Resources;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
/// <summary>
/// Represents a non-generic LINQ to Entities query against a DbContext.
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
[SuppressMessage("Microsoft.Design", "CA1010:CollectionsShouldImplementGenericInterface")]
public abstract class DbQuery : IOrderedQueryable, IListSource, IInternalQueryAdapter
#if !NET40
, IDbAsyncEnumerable
#endif
{
#region Fields and constructors
private IQueryProvider _provider;
/// <summary>
/// Internal constructor prevents external classes deriving from DbQuery.
/// </summary>
internal DbQuery()
{
}
#endregion
#region Data binding
/// <summary>
/// Returns <c>false</c>.
/// </summary>
/// <returns>
/// <c>false</c> .
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
bool IListSource.ContainsListCollection
{
get { return false; }
}
/// <summary>
/// Throws an exception indicating that binding directly to a store query is not supported.
/// Instead populate a DbSet with data, for example by using the Load extension method, and
/// then bind to local data. For WPF bind to DbSet.Local. For Windows Forms bind to
/// DbSet.Local.ToBindingList().
/// </summary>
/// <returns> Never returns; always throws. </returns>
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
IList IListSource.GetList()
{
throw Error.DbQuery_BindingToDbQueryNotSupported();
}
#endregion
#region IEnumerable
/// <summary>
/// Returns an <see cref="IEnumerator" /> which when enumerated will execute the query against the database.
/// </summary>
/// <returns> The query results. </returns>
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
IEnumerator IEnumerable.GetEnumerator()
{
return InternalQuery.GetEnumerator();
}
#endregion
#region IDbAsyncEnumerable
#if !NET40
/// <summary>
/// Returns an <see cref="IDbAsyncEnumerator" /> which when enumerated will execute the query against the database.
/// </summary>
/// <returns> The query results. </returns>
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return InternalQuery.GetAsyncEnumerator();
}
#endif
#endregion
#region IQueryable
/// <summary>
/// The IQueryable element type.
/// </summary>
public Type ElementType
{
get { return InternalQuery.ElementType; }
}
/// <summary>
/// The IQueryable LINQ Expression.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
Expression IQueryable.Expression
{
get { return InternalQuery.Expression; }
}
/// <summary>
/// The IQueryable provider.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
IQueryProvider IQueryable.Provider
{
get
{
return _provider ?? (_provider = new NonGenericDbQueryProvider(
InternalQuery.InternalContext,
InternalQuery.ObjectQueryProvider));
}
}
#endregion
#region Include
/// <summary>
/// Specifies the related objects to include in the query results.
/// </summary>
/// <remarks>
/// Paths are all-inclusive. For example, if an include call indicates Include("Orders.OrderLines"), not only will
/// OrderLines be included, but also Orders. When you call the Include method, the query path is only valid on
/// the returned instance of the DbQuery
/// <T>
/// . Other instances of DbQuery
/// <T>
/// and the object context itself are not affected.
/// Because the Include method returns the query object, you can call this method multiple times on an DbQuery
/// <T>
/// to
/// specify multiple paths for the query.
/// </remarks>
/// <param name="path"> The dot-separated list of related objects to return in the query results. </param>
/// <returns>
/// A new DbQuery <T>with the defined query path.
/// </returns>
public abstract DbQuery Include(string path);
#endregion
#region AsNoTracking
/// <summary>
/// Returns a new query where the entities returned will not be cached in the <see cref="DbContext" />.
/// </summary>
/// <returns> A new query with NoTracking applied. </returns>
public abstract DbQuery AsNoTracking();
#endregion
#region AsStreaming
/// <summary>
/// Returns a new query that will stream the results instead of buffering.
/// </summary>
/// <returns> A new query with AsStreaming applied. </returns>
public abstract DbQuery AsStreaming();
#endregion
#region Conversion to generic
/// <summary>
/// Returns the equivalent generic <see cref="DbQuery{TElement}" /> object.
/// </summary>
/// <typeparam name="TElement"> The type of element for which the query was created. </typeparam>
/// <returns> The generic set object. </returns>
public DbQuery<TElement> Cast<TElement>()
{
if (typeof(TElement)
!= InternalQuery.ElementType)
{
throw Error.DbEntity_BadTypeForCast(
typeof(DbQuery).Name, typeof(TElement).Name, InternalQuery.ElementType.Name);
}
return new DbQuery<TElement>((IInternalQuery<TElement>)InternalQuery);
}
#endregion
#region ToString
/// <summary>
/// Returns a <see cref="System.String" /> representation of the underlying query.
/// </summary>
/// <returns> The query string. </returns>
public override string ToString()
{
return InternalQuery.ToString();
}
#endregion
#region InternalQuery
/// <summary>
/// Gets the underlying internal query object.
/// </summary>
/// <value> The internal query. </value>
internal abstract IInternalQuery InternalQuery { get; }
/// <summary>
/// The internal query object that is backing this DbQuery
/// </summary>
IInternalQuery IInternalQueryAdapter.InternalQuery
{
get { return InternalQuery; }
}
#endregion
#region Hidden Object methods
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return base.GetHashCode();
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
[EditorBrowsable(EditorBrowsableState.Never)]
public new Type GetType()
{
return base.GetType();
}
#endregion
}
}

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