public void ExtendModelAsync_UpdatesModel_IfHasOnModelCreatingMethod(Type type) { // Arrange var domain = Activator.CreateInstance(type); var extender = new ConventionalModelExtender(type); var domainConfig = new DomainConfiguration(); domainConfig.EnsureCommitted(); var domainContext = new DomainContext(domainConfig); domainContext.SetProperty(type.AssemblyQualifiedName, domain); var model = GetModel(); var context = new ModelContext(domainContext) { Model = model }; // Act extender.ExtendModelAsync(context, new CancellationToken()); // Assert Assert.Same(model, context.Model); var operations = model.SchemaElements.OfType<IEdmOperation>(); Assert.Single(operations); var operation = operations.Single(); Assert.True(operation.IsBound); Assert.True(operation.IsFunction()); Assert.Equal("MostExpensive", operation.Name); Assert.Equal("ns", operation.Namespace); }
/// <inheritdoc/> public override void Initialize( DomainContext context, Type type, object instance) { Ensure.NotNull(context); Ensure.NotNull(type); context.SetProperty(type.AssemblyQualifiedName, instance); }
/// <summary> /// Initializes a new instance of the <see cref="EntityCollectionResult" /> class. /// </summary> /// <param name="query">The query that returns a collection of entities.</param> /// <param name="edmType">The EDM type reference of the entities.</param> /// <param name="context">The context where the action is executed.</param> public EntityCollectionResult(IQueryable query, IEdmTypeReference edmType, DomainContext context) : base(edmType) { Ensure.NotNull(query, "query"); Ensure.NotNull(context, "context"); this.Query = query; this.Context = context; }
/// <summary> /// Initializes a new instance of the <see cref="EntityResult" /> class. /// </summary> /// <param name="query">The query that returns an entity.</param> /// <param name="edmType">The EDM type reference of the entity.</param> /// <param name="context">The context where the action is executed.</param> public EntityResult(IQueryable query, IEdmTypeReference edmType, DomainContext context) : base(edmType) { Ensure.NotNull(query, "query"); Ensure.NotNull(context, "context"); this.Context = context; this.Result = query.SingleOrDefault(); }
/// <summary> /// Asynchronously queries for data using a domain context. /// </summary> /// <param name="context"> /// A domain context. /// </param> /// <param name="request"> /// A query request. /// </param> /// <param name="cancellationToken"> /// An optional cancellation token. /// </param> /// <returns> /// A task that represents the asynchronous /// operation whose result is a query result. /// </returns> public static async Task <QueryResult> QueryAsync( DomainContext context, QueryRequest request, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.NotNull(context, "context"); Ensure.NotNull(request, "request"); var queryContext = new QueryContext(context, request); var model = await Domain.GetModelAsync(context) as DomainModel; queryContext.Model = new DomainModel(queryContext, model.InnerModel); var handler = queryContext.GetHookPoint <IQueryHandler>(); return(await handler.QueryAsync(queryContext, cancellationToken)); }
/// <summary> /// Gets a queryable source of data using a domain context. /// </summary> /// <typeparam name="TElement"> /// The type of the elements in the queryable source. /// </typeparam> /// <param name="context"> /// A domain context. /// </param> /// <param name="name"> /// The name of an entity set, singleton or composable function import. /// </param> /// <param name="arguments"> /// If <paramref name="name"/> is a composable function import, /// the arguments to be passed to the composable function import. /// </param> /// <returns> /// A queryable source. /// </returns> /// <remarks> /// <para> /// If the name identifies a singleton or a composable function import /// whose result is a singleton, the resulting queryable source will /// be configured such that it represents exactly zero or one result. /// </para> /// <para> /// Note that the resulting queryable source cannot be synchronously /// enumerated, as the domain engine only operates asynchronously. /// </para> /// </remarks> public static IQueryable <TElement> Source <TElement>( DomainContext context, string name, params object[] arguments) { Ensure.NotNull(context, "context"); Ensure.NotNull(name, "name"); var elementType = Domain.EnsureElementType(context, null, name); if (typeof(TElement) != elementType) { // TODO GitHubIssue#24 : error message throw new ArgumentException(); } return(Domain.SourceCore <TElement>(null, name, arguments)); }
/// <summary> /// Applies initialization routines from any domain participant /// attributes specified on a domain type to a domain context. /// </summary> /// <param name="type"> /// A domain type. /// </param> /// <param name="instance"> /// A domain instance, if applicable. /// </param> /// <param name="context"> /// A domain context. /// </param> public static void ApplyInitialization( Type type, object instance, DomainContext context) { Ensure.NotNull(type, "type"); Ensure.NotNull(context, "context"); if (type.BaseType != null) { DomainParticipantAttribute.ApplyInitialization( type.BaseType, instance, context); } var attributes = type.GetCustomAttributes( typeof(DomainParticipantAttribute), false); foreach (DomainParticipantAttribute attribute in attributes) { attribute.Initialize(context, type, instance); } }
/// <summary> /// Applies disposal routines from any domain participant /// attributes specified on a domain type to a domain context. /// </summary> /// <param name="type"> /// A domain type. /// </param> /// <param name="instance"> /// A domain instance, if applicable. /// </param> /// <param name="context"> /// A domain context. /// </param> public static void ApplyDisposal( Type type, object instance, DomainContext context) { Ensure.NotNull(type, "type"); Ensure.NotNull(context, "context"); var attributes = type.GetCustomAttributes( typeof(DomainParticipantAttribute), false); foreach (DomainParticipantAttribute attribute in attributes.Reverse()) { attribute.Dispose(context, type, instance); } if (type.BaseType != null) { DomainParticipantAttribute.ApplyDisposal( type.BaseType, instance, context); } }
/// <summary> /// Tries to get the relevant type of an entity /// set, singleton, or composable function import. /// </summary> /// <param name="context"> /// A domain context. /// </param> /// <param name="name"> /// The name of an entity set, singleton or composable function import. /// </param> /// <param name="relevantType"> /// When this method returns, provides the /// relevant type of the queryable source. /// </param> /// <returns> /// <c>true</c> if the relevant type was /// provided; otherwise, <c>false</c>. /// </returns> public bool TryGetRelevantType( DomainContext context, string name, out Type relevantType) { // TODO GitHubIssue#39 : support something beyond entity sets relevantType = null; var property = this.dbContextType.GetProperty(name); if (property != null) { var type = property.PropertyType; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(DbSet<>)) { relevantType = type.GetGenericArguments()[0]; } } return relevantType != null; }
public void ExtendModelAsync_DoesntUpdatesModel_IfWithoutOnModelCreatingMethod() { // Arrange var domain = new AnyDomain(); var type = domain.GetType(); var extender = new ConventionalModelExtender(type); var domainConfig = new DomainConfiguration(); domainConfig.EnsureCommitted(); var domainContext = new DomainContext(domainConfig); domainContext.SetProperty(type.AssemblyQualifiedName, domain); var model = GetModel(); var context = new ModelContext(domainContext) { Model = model }; // Act extender.ExtendModelAsync(context, new CancellationToken()); // Assert Assert.Same(model, context.Model); Assert.Empty(model.SchemaElements.OfType<IEdmOperation>()); }
/// <summary> /// Tries to get the relevant type of an entity /// set, singleton, or composable function import. /// </summary> /// <param name="context"> /// A domain context. /// </param> /// <param name="name"> /// The name of an entity set, singleton or composable function import. /// </param> /// <param name="relevantType"> /// When this method returns, provides the /// relevant type of the queryable source. /// </param> /// <returns> /// <c>true</c> if the relevant type was /// provided; otherwise, <c>false</c>. /// </returns> public virtual bool TryGetRelevantType( DomainContext context, string name, out Type relevantType) { // TODO GitHubIssue#39 : support something beyond entity sets relevantType = null; var property = this.dbContextType.GetProperty(name); if (property != null) { var type = property.PropertyType; var genericType = type.FindGenericType(typeof (IDbSet<>)); if (genericType != null) { relevantType = genericType.GetGenericArguments()[0]; } } return relevantType != null; }
/// <summary> /// Asynchronously gets a domain model using a domain context. /// </summary> /// <param name="context"> /// A domain context. /// </param> /// <param name="cancellationToken"> /// An optional cancellation token. /// </param> /// <returns> /// A task that represents the asynchronous /// operation whose result is the domain model. /// </returns> public static async Task <IEdmModel> GetModelAsync( DomainContext context, CancellationToken cancellationToken = default(CancellationToken)) { Ensure.NotNull(context, "context"); var configuration = context.Configuration; var model = configuration.Model; if (model == null) { var modelContext = new ModelContext(context); var handler = modelContext.GetHookPoint <IModelHandler>(); var result = await handler.GetModelAsync( modelContext, cancellationToken); configuration.Model = new DomainModel(configuration, result); model = configuration.Model; } return(model); }
void IExpandableDomain.Initialize( DomainConfiguration derivedConfiguration) { if (this.IsDisposed) { throw new ObjectDisposedException(this.GetType().FullName); } if (this.domainContext != null) { throw new InvalidOperationException(); } Ensure.NotNull(derivedConfiguration, "derivedConfiguration"); var baseConfiguration = this.DomainConfiguration; var candidate = derivedConfiguration; while (candidate != baseConfiguration) { if (candidate.BaseConfiguration == null) { // TODO GitHubIssue#24 : error message throw new ArgumentException(); } candidate = candidate.BaseConfiguration; } this.domainConfiguration = derivedConfiguration; this.domainContext = this.CreateDomainContext(derivedConfiguration); DomainParticipantAttribute.ApplyInitialization( this.GetType(), this, this.domainContext); }
/// <summary> /// Disposes a domain context. /// </summary> /// <param name="context"> /// A domain context. /// </param> /// <param name="type"> /// The domain type on which this attribute was placed. /// </param> /// <param name="instance"> /// A domain instance, if applicable. /// </param> public virtual void Dispose( DomainContext context, Type type, object instance) { }
/// <summary> /// Initializes a new instance of the <see cref="InvocationContext" /> class. /// </summary> /// <param name="domainContext"> /// A domain context. /// </param> public InvocationContext(DomainContext domainContext) { Ensure.NotNull(domainContext, "domainContext"); this.DomainContext = domainContext; }
/// <summary> /// Initializes a domain context. /// </summary> /// <param name="context"> /// A domain context. /// </param> /// <param name="type"> /// The domain type on which this attribute was placed. /// </param> /// <param name="instance"> /// A domain instance, if applicable. /// </param> public virtual void Initialize( DomainContext context, Type type, object instance) { }
/// <summary> /// Tries to get the relevant type of a composable function. /// </summary> /// <param name="context"> /// A domain context. /// </param> /// <param name="namespaceName"> /// The name of a namespace containing a composable function. /// </param> /// <param name="name"> /// The name of composable function. /// </param> /// <param name="relevantType"> /// When this method returns, provides the /// relevant type of the composable function. /// </param> /// <returns> /// <c>true</c> if the relevant type was /// provided; otherwise, <c>false</c>. /// </returns> public bool TryGetRelevantType( DomainContext context, string namespaceName, string name, out Type relevantType) { // TODO GitHubIssue#39 : support composable function imports relevantType = null; return false; }
/// <inheritdoc/> public bool TryGetRelevantType( DomainContext context, string namespaceName, string name, out Type relevantType) { relevantType = null; return false; }
/// <inheritdoc/> public bool TryGetRelevantType( DomainContext context, string name, out Type relevantType) { relevantType = null; var entitySetProperty = this.AddedEntitySets .SingleOrDefault(p => p.Name == name); if (entitySetProperty != null) { relevantType = entitySetProperty .PropertyType.GetGenericArguments()[0]; } return relevantType != null; }
/// <summary> /// Releases the unmanaged resources that are used by the /// object and, optionally, releases the managed resources. /// </summary> /// <param name="disposing"> /// <c>true</c> to release both managed and unmanaged resources; /// <c>false</c> to release only unmanaged resources. /// </param> protected virtual void Dispose(bool disposing) { if (disposing) { this.domainContext = null; this.IsDisposed = true; } }