Example #1
0
        /// <summary>
        /// Asynchronously produces a base model.
        /// </summary>
        /// <param name="context">
        /// The model context.
        /// </param>
        /// <param name="cancellationToken">
        /// A cancellation token.
        /// </param>
        /// <returns>
        /// A task that represents the asynchronous
        /// operation whose result is the base model.
        /// </returns>
        public Task <IEdmModel> GetModelAsync(
            InvocationContext context,
            CancellationToken cancellationToken)
        {
            Ensure.NotNull(context, "context");

            var    model         = new EdmModel();
            var    dbContext     = context.GetApiService <DbContext>();
            var    elementMap    = new Dictionary <IAnnotatable, IEdmElement>();
            var    entityTypes   = dbContext.Model.GetEntityTypes();
            string namespaceName = CalcNamespace(dbContext, entityTypes);

            var entityContainer = new EdmEntityContainer(
                namespaceName, "Container");
            Dictionary <Type, PropertyInfo> dbSetProperties = GetDbSetPropeties(dbContext);

            // TODO GitHubIssue#36 : support complex and entity inheritance
            foreach (var efEntityType in entityTypes)
            {
                if (elementMap.ContainsKey(efEntityType))
                {
                    continue;
                }

                List <EdmStructuralProperty> concurrencyProperties;
                var entityType = ModelProducer.CreateEntityType(
                    efEntityType, model, out concurrencyProperties);
                model.AddElement(entityType);

                PropertyInfo propInfo;
                if (dbSetProperties.TryGetValue(efEntityType.ClrType, out propInfo))
                {
                    var entitySet = entityContainer.AddEntitySet(propInfo.Name, entityType);
                    if (concurrencyProperties != null)
                    {
                        model.SetOptimisticConcurrencyAnnotation(entitySet, concurrencyProperties);
                    }
                }

                elementMap.Add(efEntityType, entityType);
            }

            CreateNavigations(entityContainer, entityTypes, elementMap);

            // TODO GitHubIssue#36 : support function imports
            model.AddElement(entityContainer);

            return(Task.FromResult <IEdmModel>(model));
        }
Example #2
0
        /// <summary>
        /// Asynchronously produces a base model.
        /// </summary>
        /// <param name="context">
        /// The model context.
        /// </param>
        /// <param name="cancellationToken">
        /// A cancellation token.
        /// </param>
        /// <returns>
        /// A task that represents the asynchronous
        /// operation whose result is the base model.
        /// </returns>
        public Task <IEdmModel> GetModelAsync(
            InvocationContext context,
            CancellationToken cancellationToken)
        {
            var model         = new EdmModel();
            var domainContext = context.ApiContext;
            var dbContext     = domainContext.GetApiService <DbContext>();
            var elementMap    = new Dictionary <IAnnotatable, IEdmElement>();
            var efModel       = dbContext.Model;
            var namespaceName = efModel.EntityTypes
                                .Select(t => t.HasClrType() ? t.ClrType.Namespace : null)
                                .Where(t => t != null)
                                .GroupBy(nameSpace => nameSpace)
                                .Select(group => new
            {
                NameSpace = group.Key,
                Count     = group.Count(),
            })
                                .OrderByDescending(nsItem => nsItem.Count)
                                .Select(nsItem => nsItem.NameSpace)
                                .FirstOrDefault();

            if (namespaceName == null)
            {
                // When dbContext has not a namespace, just use its type name as namespace.
                namespaceName = dbContext.GetType().Namespace ?? dbContext.GetType().Name;
            }

            var entityTypes     = efModel.EntityTypes;
            var entityContainer = new EdmEntityContainer(
                namespaceName, "Container");

            var dbSetProperties = dbContext.GetType()
                                  .GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
                                  .Where(e => e.PropertyType.IsGenericType &&
                                         e.PropertyType.GetGenericTypeDefinition() == typeof(DbSet <>))
                                  .ToDictionary(e => e.PropertyType.GetGenericArguments()[0]);

            // TODO GitHubIssue#36 : support complex and entity inheritance
            foreach (var efEntityType in entityTypes)
            {
                if (elementMap.ContainsKey(efEntityType))
                {
                    continue;
                }

                List <EdmStructuralProperty> concurrencyProperties;
                var entityType = ModelProducer.CreateEntityType(
                    efModel, efEntityType, model, out concurrencyProperties);
                model.AddElement(entityType);
                elementMap.Add(efEntityType, entityType);

                System.Reflection.PropertyInfo propInfo;
                if (dbSetProperties.TryGetValue(efEntityType.ClrType, out propInfo))
                {
                    var entitySet = entityContainer.AddEntitySet(propInfo.Name, entityType);
                    if (concurrencyProperties != null)
                    {
                        model.SetOptimisticConcurrencyAnnotation(entitySet, concurrencyProperties);
                    }
                }
            }

            foreach (var efEntityType in entityTypes)
            {
                foreach (var navi in efEntityType.GetNavigations())
                {
                    ModelProducer.AddNavigationProperties(
                        efModel, navi, model, elementMap);
                    ModelProducer.AddNavigationPropertyBindings(
                        efModel, navi, entityContainer, elementMap);
                }
            }

            // TODO GitHubIssue#36 : support function imports
            model.AddElement(entityContainer);

            return(Task.FromResult <IEdmModel>(model));
        }