ToArray(), ToList() - Bug or no bug?

Hi - i've been doing some testing as the result of a discussion here.

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=632294&SiteID=1

I also decided to use the August CTP to test what would happen and got the following result.

{"The 'testdbModel.PCities[] ToArray[PCities](System.Collections.Generic.IEnumerable`1[testdbModel.PCities])' method is not recognized by LINQ over entities, and cannot be translated into a store expression."}

and

{"The 'System.Collections.Generic.List`1[testdbModel.PCities] ToList[PCities](System.Collections.Generic.IEnumerable`1[testdbModel.PCities])' method is not recognized by LINQ over entities, and cannot be translated into a store expression."}

So there seems to be a number of variations on what is supposed to happen. Anyone shed any light? My guess is they should all result in similar behavior (exception or not), but at the moment they don't :)

Here is the code i used for the ADO.Net version.

using System;

using System.Collections.Generic;

using System.Text;

using System.Data;

using System.Data.Common;

using System.Data.Mapping;

using System.Data.Objects;

using System.Query;

using testdbModel;

namespace ConsumeTestXLinq

{

classProgram

{

staticvoid Main(string[] args)

{

using (testdb db =newtestdb("name=testdbConnectionString"))

{

#region Using ToArray()

var query =from min db.Names

selectnew {m.id, m.name,

pcities = (from cin db.PCities

where c.id == m.id

select c).ToArray()

};

#endregion

#region Using ToList()

//var query = from m in db.Names

//select new {m.id, m.name,

//pcities = (from c in db.PCities

// where c.id == m.id

// select c).ToList()

//};

#endregion

foreach (var tin query)

{

Console.WriteLine(String.Format("Name : {0}", t.name));

Console.WriteLine(String.Format("Cities ({0})", t.pcities.Length));

for (int i = 0; i < t.pcities.Length; i++)

Console.WriteLine(String.Format(" City : {0}", t.pcitiesIdea.city));

Console.WriteLine(Environment.NewLine);

}

}

}

}

}

steven
http://stevenR2.com

[5698 byte] By [StevenR2] at [2008-2-13]
# 1

Hi Steven,

You can use several patterns to create arrays or lists, e.g.:

Query<T> myQuery = ...;
List<T> l1 = ((IEnumerable<T>)myQuery).ToList();
List<T> l2 = new List<T>(myQuery);

The LINQ implementation tries to maintain an explicit boundary between the client and store. Certain operations (like ToList and ToArray) which can only be evaluated in the client require explicit calls. In the first example (l1), we cast to IEnumerable to indicate the in-memory implementation of ToList should be used. We maintain this boundary to minimize surprises when executing LINQ queries, because certain expressions, if evaluated in the client, can be extremely expensive.

-Colin

ColinMeek at 2007-8-31 > top of Msdn Tech,Visual Studio Orcas,ADO.NET Orcas...
# 2
I think the problem with the original code posted here is that the expression tree evaluator got confused - it didn't have enough contextual information to determine that it was supposed to be dumping the sub-query to an in-memory representation rather than performing a model-side subquery.

As Colin points out, if you force the clue that you want the in-memory representation rather than an affectation of the expression tree, both work fine.

I've run into this a handful of times in LINQ to SQL.

KevinHoffman at 2007-8-31 > top of Msdn Tech,Visual Studio Orcas,ADO.NET Orcas...

Visual Studio Orcas

Site Classified