Пример #1
0
        private static string ConvertToSqlWhere(QueryIsNotNull queryIsNotNull, TypeReflector typeReflector, List <KeyValuePair <int, object> > parameters, IDictionary <string, CrossApplyDefinition> crossApplyDefinitions)
        {
            var reflectedType = typeReflector.Navigate(queryIsNotNull.Field);

            if (reflectedType == null)
            {
                throw new InvalidOperationException($"Unable to find property '{queryIsNotNull.Field}' on type '{typeReflector}'");
            }
            return($"JSON_VALUE(_document,'$.{queryIsNotNull.Field}') IS NOT NULL");
        }
Пример #2
0
        private static FieldType ResolveField(string originalPath, TypeReflector typeReflector, IDictionary <string, CrossApplyDefinition> crossApplyDefinitions, bool appendToGroupByClause = false)
        {
            var fieldTypes = typeReflector.Navigate(originalPath).ToList();

            if (!fieldTypes.Any())
            {
                throw new InvalidOperationException($"Property '{originalPath}' is invalid");
            }

            var resultingPath = new List <string>();
            var tempPath      = new List <string>();
            CrossApplyDefinition lastCrossApplyDefinition = null;

            foreach (var fieldType in fieldTypes)
            {
                if (fieldType.IsObjectArray)
                {
                    if (fieldType == fieldTypes.Last())
                    {
                        throw new InvalidOperationException();
                    }

                    tempPath.Add(fieldType.Name);

                    lastCrossApplyDefinition = new CrossApplyDefinition
                    {
                        Parent = fieldType.Parent?.Path != null ? crossApplyDefinitions[fieldType.Parent.Path] : null,
                        Name   = string.Join(".", tempPath)
                    };

                    crossApplyDefinitions[lastCrossApplyDefinition.Name] = lastCrossApplyDefinition;
                    if (appendToGroupByClause)
                    {
                        lastCrossApplyDefinition.AppendToGroupBy = true;
                    }

                    tempPath.Clear();
                }
                else
                {
                    resultingPath.Add(fieldType.Name);
                    tempPath.Add(fieldType.Name);
                }
            }

            return(new FieldType()
            {
                Type = fieldTypes.Last(),
                Path = string.Join(".", resultingPath),
                ParentField = lastCrossApplyDefinition?.Path ?? "_document"
            });
        }
Пример #3
0
        public void TypeReflectorTest()
        {
            var typePost = TypeReflector.Create <Post>();

            Assert.IsNotNull(typePost);
            Assert.AreEqual(9, typePost.Properties.Count);

            Assert.AreEqual(typeof(string), typePost.Properties["Title"].PropertyType);
            Assert.AreEqual(typeof(List <Comment>), typePost.Properties["Comments"].PropertyType);
            Assert.AreEqual(typeof(string[]), typePost.Properties["Tags"].PropertyType);

            var userTypes = TypeReflector.Navigate <Post>("Author.Username").ToList();

            Assert.IsNotNull(userTypes);
            Assert.AreEqual(typeof(User), userTypes[0].Type);
            Assert.AreEqual(typeof(string), userTypes[1].Type);

            var tagsType = TypeReflector.Navigate <Post>("Tags").ToList();

            Assert.IsNotNull(tagsType);
            Assert.IsTrue(tagsType[0].IsValueArray);
            Assert.AreEqual(typeof(string), tagsType[0].Type);

            var commentsType = TypeReflector.Navigate <Post>("Comments.Content").ToList();

            Assert.IsNotNull(commentsType);
            Assert.IsTrue(commentsType[0].IsObjectArray);
            Assert.AreEqual(typeof(Comment), commentsType[0].Type);
            Assert.AreEqual(typeof(string), commentsType[1].Type);

            userTypes = TypeReflector.Navigate <Post>("Comments.Author.Username").ToList();
            Assert.IsNotNull(userTypes);
            Assert.IsTrue(userTypes[0].IsObjectArray);
            Assert.AreEqual(typeof(Comment), userTypes[0].Type);
            Assert.AreEqual(typeof(User), userTypes[1].Type);
            Assert.AreEqual(typeof(string), userTypes[2].Type);

            var replieTypes = TypeReflector.Navigate <Post>("Comments.Replies.Author.Username").ToList();

            Assert.IsNotNull(replieTypes);
            Assert.IsTrue(replieTypes[0].IsObjectArray);
            Assert.AreEqual(typeof(Comment), replieTypes[0].Type);
            Assert.IsTrue(replieTypes[1].IsObjectArray);
            Assert.AreEqual(typeof(Reply), replieTypes[1].Type);
            Assert.AreEqual(typeof(User), replieTypes[2].Type);
            Assert.AreEqual(typeof(string), replieTypes[3].Type);
        }
Пример #4
0
        public async Task EnsureIndexAsync(NsDatabase database, string tableName, TypeReflector typeReflector, string path, bool unique = false, bool ascending = true)
        {
            Validate.NotNull(database, nameof(database));
            Validate.NotNullOrEmptyOrWhiteSpace(tableName, nameof(tableName));
            Validate.NotNullOrEmptyOrWhiteSpace(path, nameof(path));
            Validate.NotNull(typeReflector, nameof(typeReflector));

            /*
             * USE [DatabaseTest_Index]
             * IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'[dbo].[posts]') AND name = 'Updated')
             * BEGIN
             * ALTER TABLE [dbo].[Posts]
             * ADD [Updated] AS (CONVERT(datetime2, JSON_VALUE([_document],'$.Updated'), 102))
             * END
             * IF NOT EXISTS(SELECT * FROM sys.indexes WHERE name = 'IDX_Updated' AND object_id = OBJECT_ID('posts'))
             * BEGIN CREATE  NONCLUSTERED INDEX [IDX_Updated] ON [dbo].[posts]
             * ( [Updated] DESC )
             * WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
             * END
             */

            var fieldTypes = typeReflector.Navigate(path).ToList();

            if (!fieldTypes.Any())
            {
                throw new InvalidOperationException($"Path '{path}' doesn't represent a valid property");
            }

            if (fieldTypes.Any(_ => _.IsArray))
            {
                throw new InvalidOperationException($"Unable to create an index for path '{path}', it traverses arrays or collections of objects");
            }

            var    columnName       = path.Replace(".", "_");
            string addColumnCommand = null;
            var    lastFieldType    = fieldTypes.Last();

            if (lastFieldType.Is(typeof(DateTime)))
            {
                addColumnCommand = $"ADD [{columnName}] AS (CONVERT(datetime2, JSON_VALUE([_document],'$.{path}'), 102))";
            }
            else if (lastFieldType.Is(typeof(int)))
            {
                addColumnCommand = $"ADD [{columnName}] AS (CONVERT(int, JSON_VALUE([_document],'$.{path}')))";
            }

            if (addColumnCommand == null)
            {
                throw new InvalidOperationException($"Type '{lastFieldType.Type}' is not (yet?) supported for indexes");
            }

            await ExecuteNonQueryAsync(
                $"USE [{database.Name}]",
                $"IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N\'[dbo].[{tableName}]\') AND name = \'{columnName}\')",
                $"BEGIN",
                $"ALTER TABLE [dbo].[Posts]",
                addColumnCommand,
                $"END",
                $"IF NOT EXISTS(SELECT * FROM sys.indexes WHERE name = \'IDX_{columnName}\' AND object_id = OBJECT_ID(\'{tableName}\'))",
                $"BEGIN",
                $"CREATE {(unique ? "UNIQUE" : string.Empty)} NONCLUSTERED INDEX [IDX_{columnName}] ON [dbo].[{tableName}]",
                $"( [{columnName}] {(ascending ? "ASC" : "DESC")} )",
                $"WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]",
                $"END");
        }