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); }
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; } } }
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; } } }
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; } } }
public T Add <T>(T entity) where T : class, IEntity { context.Set <T>().Add(entity); return(entity); }