Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"new" inside concrete type projection is only called once

I've simple Linq2Sql query:

var result = from t in MyContext.MyItems
             select new MyViewModelClass()
             {
                 FirstProperty = t,
                 SecondProperty = new SomeLinq2SqlEntity()
             }      

The problem is that it seems that new SomeLinq2SqlEntity() is executed only once for the sequence, so all instances of MyViewModelClass in result of the query share the link to one object.

Update: Here is how I quickly check it:

result[0].SecondProperty.MyField = 10;

Using debugger I can check that MyField was set to 10 in all instances.

When I replace LINQ query with foreach, it works as expected:

  var result = from t in MyContext.MyItems select t;
  var list = new List<MyViewModelClass>();
  foreach (var item in result)
  {
      list.add(new MyViewModelClass()
             {
                 FirstProperty = item,
                 SecondProperty = new SomeLinq2SqlEntity()
             });       
  }

I haven't found the root of the problem, but the post marked as asnwer provides good workaround. Check this asnwer for the detailed description: "new" inside concrete type projection is only called once

like image 848
artvolk Avatar asked Aug 01 '11 14:08

artvolk


2 Answers

It probably has something to do with weird IQueryable implementation of your provider. Aducci's answer extracts data from database with AsEnumerable() call and performs the query on that set, which is different from performing it through IQueryable.

For example IQueryable builds the ExpressionTree which it later parses according to the concrete provider (i.e. executing shared code once for optimization), while IEnumerable accepts Func and performs it as you would expect.

You can read more here:

http://msdn.microsoft.com/en-us/vcsharp/ff963710

like image 56
Grozz Avatar answered Oct 20 '22 09:10

Grozz


Have you tried using adding the SomeLinq2SqlEntity object with linq to objects?

var result = (from t in MyContext.MyItems
             select new
             {
                 FirstProperty = t
             })
             .AsEnumerable() 
             .Select(t => new MyViewModelClass()
             {
                 FirstProperty = t.FirstProperty ,
                 SecondProperty = new SomeLinq2SqlEntity();
             });   
like image 34
Aducci Avatar answered Oct 20 '22 09:10

Aducci