public void CanSelectDynamic()
        {
            using (var db = new EF7BloggContext())
            {
                var authorToSerachFor = Fixture.Create<string>();
                var blog = new Blog() { Name = Fixture.Create<string>(), Description = Fixture.Create<string>() };

                db.AddRange(new[] { blog });

                db.SaveChanges();

                var retrievedBlog = db.Set<Blog>()
                    .Include(p => p.Posts)
                    .ToList();
                //.Select(p => new { p.Author })
                //.ToList();
                //.SelectDynamic(new[] { nameof(Blog.Author) });

                foreach (var blog1 in retrievedBlog)
                {
                    Assert.IsNotNull(blog1);
                }
            }
        }
        private Type CreateLambbda(out Expression <Func <T, dynamic> > lambda)
        {
            /*
             * Based in the follwing:
             *
             * var projector = rep.PropertySelectBuilder(blog)
             *      .Select(p => p.Name)
             *      .Include<Post>(m => m.Posts, p => p.Text)
             *      .Build();
             *
             *
             * Output lambda to be used as expression in:
             *
             * context.Set<T>().
             *  Where(p => p.Id == id).
             *  Select(lamdba.Expression).
             *  Single();
             *
             *
             * where lambda will look (using AllProjections in the builder), using example projector above
             *
             * p = new
             * {
             *  p => p.Name,
             *  Posts =     from post in context.Set<Post>()
             *              where post.BlogId == _id
             *              select new
             *              {
             *                  Text = pp.Text
             *              }
             * }
             */

            List <KeyValuePair <string, Type> > anonymousTypeProperties = new List <KeyValuePair <string, Type> >();
            List <Expression>   anonymousTypePropertiesValues           = new List <Expression>();
            ParameterExpression lambdaParameter = Expression.Parameter(typeof(T), "p");

            foreach (var projection in AllProjections.BaseEntityProjections)
            {
                var projectionLambda = projection as LambdaExpression;

                MemberExpression member = ParameterHelper.GetMemberExpression(projectionLambda);

                var propertyInfo = (PropertyInfo)member.Member;
                var propertyName = propertyInfo.Name;
                var propertyType = propertyInfo.PropertyType;

                var memberAccess = Expression.Property(lambdaParameter, propertyName);

                anonymousTypeProperties.Add(new KeyValuePair <string, Type>(propertyName, propertyType));
                anonymousTypePropertiesValues.Add(memberAccess);
            }

            foreach (var navigationProperty in AllProjections.NavigationPropertiesProjections)
            {
                var navigationProperyType = navigationProperty.Type;

                // Creates the <T>.where(p => p.id == id) part of the expression
                MethodCallExpression whereCallExpression = CreateWhereCall <T>(_id, navigationProperyType);

                ParameterExpression p1 = Expression.Parameter(navigationProperyType, "p1");
                var navigationPropertyAnoymousTypeProperties = new List <KeyValuePair <string, Type> >();
                List <MemberExpression> navigationPropertyAnoymousTypePropertiesValues = new List <MemberExpression>();
                foreach (var projection in navigationProperty.Projections)
                {
                    var navigationPropertyProjection = projection as LambdaExpression;

                    MemberExpression member = ParameterHelper.GetMemberExpression(navigationPropertyProjection);

                    var propertyInfo = (PropertyInfo)member.Member;
                    var propertyName = propertyInfo.Name;
                    var propertyType = propertyInfo.PropertyType;

                    var memberAccess = Expression.Property(p1, propertyName);

                    navigationPropertyAnoymousTypeProperties.Add(new KeyValuePair <string, Type>(propertyName, propertyType));
                    navigationPropertyAnoymousTypePropertiesValues.Add(memberAccess);
                }

                var anonymousTypeOfNavigationPropertyProjection =
                    AnonymousTypeUtils.CreateType(navigationPropertyAnoymousTypeProperties);
                Type typeOfSubProj = null;
                var  anonymousTypeOfNavigationPropertyProjectionConstructor = anonymousTypeOfNavigationPropertyProjection
                                                                              .GetConstructor(navigationPropertyAnoymousTypeProperties.Select(kv => kv.Value).ToArray());
                typeOfSubProj = anonymousTypeOfNavigationPropertyProjectionConstructor.ReflectedType;

                var selectMethod        = typeof(Queryable).GetMethods().Where(m => m.Name == "Select").ToList()[0];
                var genericSelectMethod = selectMethod.MakeGenericMethod(navigationProperyType, typeOfSubProj);

                var newInstanceOfTheGenericType = Expression.New(anonymousTypeOfNavigationPropertyProjectionConstructor,
                                                                 navigationPropertyAnoymousTypePropertiesValues);

                var projectionLamdba = Expression.Lambda(newInstanceOfTheGenericType, p1);

                MethodCallExpression selctCallExpression = Expression.Call(
                    genericSelectMethod,
                    whereCallExpression,
                    projectionLamdba);

                var provider = ((IQueryable)_context.Set <T>()).Provider;
                // TODO, Is it ok to assume navigation properties has the same provider?
                var theMethods    = typeof(IQueryProvider).GetMethods();
                var createQMethd  = theMethods.Where(name => name.Name == "CreateQuery").ToList()[1];
                var speciifMethod =
                    createQMethd.MakeGenericMethod(anonymousTypeOfNavigationPropertyProjectionConstructor.ReflectedType);
                var navigationProppertyQueryWithProjection1 = speciifMethod.Invoke(provider, new object[] { selctCallExpression });

                Type genericFunc         = typeof(IEnumerable <>);
                Type funcOfTypeOfSubProj = genericFunc.MakeGenericType(typeOfSubProj);

                var allMethodsOnEnumerableClass = typeof(Enumerable).GetMethods();
                var genericToListMethod         = allMethodsOnEnumerableClass.Where(m => m.Name == "ToList").ToList()[0];

                var toListOfTypeOfSubProj = genericToListMethod.MakeGenericMethod(typeOfSubProj);

                MethodCallExpression toListExpression11 = Expression.Call(
                    toListOfTypeOfSubProj,
                    Expression.Constant(navigationProppertyQueryWithProjection1));

                anonymousTypeProperties.Add(new KeyValuePair <string, Type>(navigationProperty.Name, funcOfTypeOfSubProj));
                anonymousTypePropertiesValues.Add(toListExpression11);
            }

            var projectedEntityAnonymousType = AnonymousTypeUtils.CreateType(anonymousTypeProperties);

            var constructor = projectedEntityAnonymousType.GetConstructor(anonymousTypeProperties.Select(p => p.Value).ToArray());

            var anonymousTypeInstance = Expression.New(constructor, anonymousTypePropertiesValues);

            lambda = Expression.Lambda <Func <T, dynamic> >(anonymousTypeInstance, lambdaParameter);
            return(projectedEntityAnonymousType);
        }
Beispiel #3
0
        public void CanRetriveUsingTableValuedFunction()
        {
            /*
            USE [EF7]
            GO

            SET ANSI_NULLS ON
            GO

            SET QUOTED_IDENTIFIER ON
            GO

            DROP FUNCTION[dbo].[SearchBlogs];

            GO
            CREATE FUNCTION[dbo].[SearchBlogs]
            (
                @param2 nvarchar(200)
            )
            RETURNS @returntable TABLE
            (
                Id int,
                Author nvarchar(200),
                Name nvarchar(200),
                Description nvarchar(200)
            )
            AS
            BEGIN
                INSERT @returntable
                SELECT
                    blogs.Id, blogs.Name, blogs.Author, blogs.Description
                from dbo.Blog blogs
                where
                    blogs.Name like @param2
                RETURN
            END
            */

            using (var db = new EF7BloggContext(ServiceProvider))
            {
                //EnsureCleanDatabase(db);

                db.Blogs.Add(new Blog() { Name = "ADO.NET Blog" });
                db.Blogs.Add(new Blog() { Name = "Visual Studio" });
                db.Blogs.Add(new Blog() { Name = ".NET Blog" });

                db.SaveChanges();

                /*
                1. Parameterized, not open to sql injection
                2. Strongly typed (renaming properties)
                3. The order by is happening in the database, not in memory.
                */
                var nameToSerachFor = "blog";
                var seachedBlogs = db.Set<Blog>()
                    .FromSql("select * from dbo.SearchBlogs (@p0)", nameToSerachFor);
                //.OrderBy(b => b.Name); // <-- Strongly typed

                foreach (var blog in seachedBlogs)
                {
                    var found = blog.Name;
                }
            }
        }
Beispiel #4
0
        public void CanPerformSomeInMermoryAndSomeInDatabase()
        {
            using (var db = new EF7BloggContext(ServiceProvider))
            {
                //EnsureCleanDatabase(db);

                db.Blogs.Add(new Blog() { Name = "ADO.NET Blog" });
                db.Blogs.Add(new Blog() { Name = "Visual Studio" });
                db.Blogs.Add(new Blog() { Name = ".NET Blog" });

                db.SaveChanges();

                var seachedBlogs = db.Set<Blog>()
                    .OrderBy(b => GetSortName(b.Name))
                    .Where(b => b.Name.Contains(("blog"))); // Some parts of the query in db (where) and some inmemory (GetSortName)

                foreach (var blog in seachedBlogs)
                {
                    var found = blog.Name;
                }
            }
        }
Beispiel #5
0
        public void CanIncludeThenIncludeNavigationProperties()
        {
            using (var db = new EF7BloggContext(ServiceProvider))
            {
                //EnsureCleanDatabase(db);

                db.Blogs.Add(new Blog() { Name = "ADO.NET Blog" });
                db.Blogs.Add(new Blog() { Name = "Visual Studio" });
                db.Blogs.Add(new Blog() { Name = ".NET Blog" });

                db.SaveChanges();

                var seachedBlogs = db.Set<Blog>()
                    .Include((b => b.Posts))        // Eager loading, in ef6 10 blog with 10 posts each
                    .Where(b => b.Name.Contains("blog"));

                foreach (var blog in seachedBlogs)
                {
                    var found = blog.Name;
                }
            }
        }
Beispiel #6
0
        public T Add <T>(T entity) where T : class, IEntity
        {
            context.Set <T>().Add(entity);

            return(entity);
        }