Beispiel #1
0
        private static IEdmEntityType CreateEntityType(
            IModel efModel,
            IEntityType efEntityType,
            EdmModel model,
            out List <EdmStructuralProperty> concurrencyProperties)
        {
            // TODO GitHubIssue#36 : support complex and entity inheritance
            var entityType = new EdmEntityType(
                efEntityType.ClrType.Namespace, efEntityType.ClrType.Name);

            concurrencyProperties = null;
            foreach (var efProperty in efEntityType.GetProperties())
            {
                var type = ModelProducer.GetPrimitiveTypeReference(efProperty);
                if (type != null)
                {
                    string defaultValue = null;
                    RelationalPropertyAnnotations annotations = new RelationalPropertyAnnotations(efProperty, null);

                    if (annotations.DefaultValue != null)
                    {
                        defaultValue = annotations.DefaultValue.ToString();
                    }

                    var property = entityType.AddStructuralProperty(
                        efProperty.Name,
                        type,
                        defaultValue,
                        EdmConcurrencyMode.None); // alway None:replaced by OptimisticConcurrency annotation

                    // TODO GitHubIssue#57: Complete EF7 to EDM model mapping
                    if (efProperty.StoreGeneratedAlways)
                    {
                        SetComputedAnnotation(model, property);
                    }

                    if (efProperty.IsConcurrencyToken)
                    {
                        concurrencyProperties = concurrencyProperties ?? new List <EdmStructuralProperty>();
                        concurrencyProperties.Add(property);
                    }
                }
            }

            var key = efEntityType.GetPrimaryKey();

            if (key != null)
            {
                entityType.AddKeys(key.Properties
                                   .Select(p => entityType.FindProperty(p.Name))
                                   .Cast <IEdmStructuralProperty>());
            }

            return(entityType);
        }
Beispiel #2
0
 private static void CreateNavigations(
     EdmEntityContainer entityContainer,
     IEnumerable <IEntityType> entityTypes,
     Dictionary <IAnnotatable, IEdmElement> elementMap)
 {
     foreach (var efEntityType in entityTypes)
     {
         foreach (var navi in efEntityType.GetNavigations())
         {
             ModelProducer.AddNavigationProperties(navi, elementMap);
             ModelProducer.AddNavigationPropertyBindings(navi, entityContainer, elementMap);
         }
     }
 }
Beispiel #3
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));
        }
Beispiel #4
0
 static ModelProducer()
 {
     Instance = new ModelProducer();
 }
Beispiel #5
0
        private static void AddNavigationProperties(
            IModel efModel,
            INavigation navigation,
            EdmModel model,
            IDictionary <IAnnotatable, IEdmElement> elementMap)
        {
            if (!navigation.PointsToPrincipal())
            {
                return;
            }

            var naviPair         = new INavigation[] { navigation, navigation.FindInverse() };
            var navPropertyInfos = new EdmNavigationPropertyInfo[2];

            for (var i = 0; i < 2; i++)
            {
                var navi = naviPair[i];
                if (navi == null)
                {
                    continue;
                }

                var efEntityType = navi.DeclaringEntityType;
                if (!elementMap.ContainsKey(efEntityType))
                {
                    continue;
                }

                var entityType         = elementMap[efEntityType] as IEdmEntityType;
                var efTargetEntityType = navi.GetTargetType();
                if (!elementMap.ContainsKey(efTargetEntityType))
                {
                    continue;
                }

                var targetEntityType = elementMap[efTargetEntityType] as IEdmEntityType;
                navPropertyInfos[i] = new EdmNavigationPropertyInfo()
                {
                    ContainsTarget     = false,
                    Name               = navi.Name,
                    Target             = targetEntityType,
                    TargetMultiplicity = ModelProducer.GetEdmMultiplicity(navi),
                };
                var foreignKey = navi.ForeignKey;
                if (foreignKey != null && navi.PointsToPrincipal())
                {
                    navPropertyInfos[i].OnDelete = foreignKey.DeleteBehavior == DeleteBehavior.Cascade ?
                                                   EdmOnDeleteAction.Cascade : EdmOnDeleteAction.None;
                    navPropertyInfos[i].DependentProperties = foreignKey.Properties
                                                              .Select(p => entityType.FindProperty(p.Name) as IEdmStructuralProperty);
                    navPropertyInfos[i].PrincipalProperties = foreignKey.PrincipalKey.Properties
                                                              .Select(p => targetEntityType.FindProperty(p.Name) as IEdmStructuralProperty);
                }
            }

            if (navPropertyInfos[0] == null && navPropertyInfos[1] != null)
            {
                var efEntityType = navigation.GetTargetType();
                var entityType   = elementMap[efEntityType] as EdmEntityType;
                if (entityType.FindProperty(navPropertyInfos[1].Name) == null)
                {
                    entityType.AddUnidirectionalNavigation(navPropertyInfos[1]);
                }
            }

            if (navPropertyInfos[0] != null && navPropertyInfos[1] == null)
            {
                var efEntityType = navigation.DeclaringEntityType;
                var entityType   = elementMap[efEntityType] as EdmEntityType;
                if (entityType.FindProperty(navPropertyInfos[0].Name) == null)
                {
                    entityType.AddUnidirectionalNavigation(navPropertyInfos[0]);
                }
            }

            if (navPropertyInfos[0] != null && navPropertyInfos[1] != null)
            {
                var efEntityType = navigation.DeclaringEntityType;
                var entityType   = elementMap[efEntityType] as EdmEntityType;
                if (entityType.FindProperty(navPropertyInfos[0].Name) == null)
                {
                    entityType.AddBidirectionalNavigation(
                        navPropertyInfos[0], navPropertyInfos[1]);
                }
            }
        }
Beispiel #6
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));
        }
Beispiel #7
0
 static ModelProducer()
 {
     Instance = new ModelProducer();
 }