Quantcast
Channel: Entity Framework
Viewing all articles
Browse latest Browse all 10318

Commented Feature: Support projections to strongly typed collections in LINQ to Entities [808]

$
0
0
Consider the repro below. This code attempts to execute a query which projects into DTO objects. One DTO object (BlogDto) contains a collection of the other DTO (PostDto). If the property that represents this collection is type as IEnumerable<PostDto> then everything is fine because the select returns an IEnumerable<PostDto> and LINQ to Entities handles it.

However, if the property is types as List<Dto> or some other strongly typed collection, then the query must be changed so that the Select in the projection returns a List. (If this is not done C# won't compile it.) This can be attempted either with a call to ToList or a cast. But LINQ to Entities does not support either of these things, even though the underlying collection is a List<PostDto>. LINQ to Entities should be able to detect these patterns and determine that they are no-ops.

More details can be found in this discussion and the linked blog article: http://entityframework.codeplex.com/discussions/430165

This bug is related and could possibly be considered a duplicate:
http://entityframework.codeplex.com/workitem/111

```

public class BlogDto
{
public int Id { get; set; }
public string Title { get; set; }

// Change this to IEnumerbale<PostDto> and remove the cast/ToList below to make work
public virtual List<PostDto> Posts { get; set; }
}

public class PostDto
{
public int Id { get; set; }
public string Title { get; set; }

public int BlogId { get; set; }
}

public class Blog
{
public int Id { get; set; }
public string Title { get; set; }

public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
public int Id { get; set; }
public string Title { get; set; }

public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}

public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}

internal class Program
{
private static void Main(string[] args)
{
using (var context = new BlogContext())
{
context.Posts.Add(new Post {Title = "Open source FTW", Blog = new Blog {Title = "One Unicorn"}});
context.SaveChanges();
}

using (var context = new BlogContext())
{
var blogs = context.Blogs.Select(
b => new BlogDto
{
Id = b.Id,
Title = b.Title,
// If Posts is typed as IEnumerbale<PostDto> then cast can be removed and query will work
// Note that ToList is another option here that also currently doesn't work
Posts = (List<PostDto>)b.Posts.Select(
p => new PostDto
{
Id = p.Id,
Title = p.Title
})
});

foreach (var blog in blogs)
{
Console.WriteLine("Blog: {0}", blog.Title);
foreach (var post in blog.Posts)
{
Console.WriteLine(" Post: {0}", post.Title);
}
}
}
}
}

```

Current stack trace:

Unhandled Exception: System.NotSupportedException: Unable to cast the type 'System.Collections.Generic.IEnumerable`1' to
type 'System.Collections.Generic.List`1'. LINQ to Entities only supports casting EDM primitive or enumeration types.
at System.Data.Objects.ELinq.ExpressionConverter.ValidateAndAdjustCastTypes(TypeUsage toType, TypeUsage fromType, Typ
e toClrType, Type fromClrType)
at System.Data.Objects.ELinq.ExpressionConverter.GetCastTargetType(TypeUsage fromType, Type toClrType, Type fromClrTy
pe, Boolean preserveCastForDateTime)
at System.Data.Objects.ELinq.ExpressionConverter.CreateCastExpression(DbExpression source, Type toClrType, Type fromC
lrType)
at System.Data.Objects.ELinq.ExpressionConverter.ConvertTranslator.TranslateUnary(ExpressionConverter parent, UnaryEx
pression unary, DbExpression operand)
at System.Data.Objects.ELinq.ExpressionConverter.UnaryTranslator.TypedTranslate(ExpressionConverter parent, UnaryExpr
ession linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression l
inq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, Memb
erInitExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression l
inq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpre
ssionBinding& binding)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConvert
er parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter
parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionCo
nverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, Meth
odCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression l
inq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.Convert()
at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Data.Entity.Internal.Linq.InternalQuery`1.GetEnumerator()
at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator()
at ConsoleApplication18.Program.Main(String[] args) in c:\Stuff\ConsoleApplication18\ConsoleApplication18\Program.cs:
line 72
Comments: your suggestion.... very helpful!, thanks.... It's work for me... :D

Viewing all articles
Browse latest Browse all 10318

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>