c# - The Same instance of a list for all elements when using Select New List<> in linq to sql -


the same instance of list elements when using select new list<> in linq sql

i ran across odd behavior clarifying. have workaround issue, don’t understand why it’s happening in first place , suspect either bug linq sql or understanding things wrong.

the problem having select clause on linq sql statement.

consider following code, db.messagestatustypes “table”. using table in custom database doesn’t seem matter table use long there @ least 2 rows in table.

list<list<string>> construct = (from o in db.messagestatustypes                                     select new list<string>() { "hello" }                 ).tolist(); construct[0].add("world"); return construct[1].count(); 

what expect construct list of x new list. x number of rows in db.

and if modify 1 of lists others not modified. not case. in example above if add string world first array, gets added x of arrays.

contrast same code without linq sql

list<int> ilist = new list<int>() { 1, 2, 3, 4 }; list<list<string>> construct = (from in ilist                                   select new list<string>() { "hello" }                    ).tolist(); construct[0].add("world"); return construct[1].count(); 

in case when add world first list other lists not affected.

could please explain why different behavior , if there know or unknow bug linq sql?

   using system;    using system.collections.generic;    using system.configuration;    using system.linq;    using system.text;    using system.threading.tasks;     namespace consoleapp {      class program {          static void main(string[] args) {          int count1 = function1(); //return 1          int count2 = function2(); //return 2?          }          static int function1() {          list<int> ilist = new list<int>() { 1, 2, 3, 4 };          list<list<string>> construct = (from in ilist                                          select new list<string>() { "hello" }                           ).tolist();          construct[0].add("world");          return construct[1].count();        }         static int function2() {          data.dbmanager dbmanager = new    data.dbmanager(throwexceptiononlocal: false);          string connectionstring =    configurationmanager.connectionstrings["data.properties.settings   .factorycommunicationsconnectionstring"].connectionstring;          using (data.factorycommunicationscontext db = new    data.factorycommunicationscontext(connectionstring)) {             list<list<string>> construct = (from o in db.messagestatustypes                                            select new list<string>() { "hello" }                        ).tolist();            construct[0].add("world");            return construct[1].count();          }        }        }       } 

i raised ticket microsoft , confirmed expected behavior , not bug.

what boils down following:

  1. linq objects , linq2sql different. quote linq2sql dev - “first of all, linq2sql has nothing linq object. iqueryprovider object decides how execute iqueryable queries. apparently, use different iqueryprovider.

  2. linq2sql in maintenance mode. response microsoft: “i encourage investigate using entity framework rather raw linq sql, in order greater flexibility provided ef. i’m pretty sure microsoft no longer putting investment enhancements linqtosql, , strictly in maintenance mode now. if confirm it’s bug, there’s high bar approving fixes. “

  3. linq sql not @ interpreting mean when translating select clause when contains list.

consider following statements:

list<list<string>> construct = (from o in db.messagestatustypes select new list<string>() { "hello" }).tolist(); 

this microsoft’s response

“linq2sql converts linq expressions sqlexpression, , generates sql based on sqlexpressions. here catch. [new list() { "hello" }] considered constantexpression(this done compiler) , converted sqlvalue expression. hence executes once.”

because executes once odd behavior same list assigned every result.

now consider other similar statements

list<list<string>> construct = (from o in db.messagestatustypes select generatelist() ).tolist();  static list<string> generatelist() {   if (datetime.now.ticks % 2 == 0) {     return new list<string> { "hello" };   }   else {     return new list<string> { "hello" };   } } 

this returns same thing, since generatelist() considered constant expression. generatelist() called once. key when compiler doesn’t think depends on data returned sql @ considers constant expression.

list<list<string>> construct = (from o in db.messagestatustypes select new list<string>() { o.description}).tolist();  

this statement seems should work. since depends on data returned. run different problem (runtime exception - cannot create query result of type 'system.collections.generic.list`1[system.string]'). linq2sql doesn’t support this.

here official response linq2sql dev:

“this different behavior caused conversion between linq expression , linq2sql expression. [new list() { o.description}] converted sqlclientarray expression supports clr array type.”

which takes work around.

list<list<string>> construct = (from o in db.messagestatustypes select generatelist(o.description) ).tolist();  static list<string> generatelist(string description) {   return new list<string> { “hello” }; } 

this give expected results, here reason linq2sql dev:

“this methodcall expression , converted sqlmethodcall expression through linq2sql generate il dynamically”

the other workaround mentioned in comments avoid creating list in linq2sql statement. instead first data use a linq object statement create desired object lists.


Comments

Popular posts from this blog

javascript - Thinglink image not visible until browser resize -

firebird - Error "invalid transaction handle (expecting explicit transaction start)" executing script from Delphi -

mongodb - How to keep track of users making Stripe Payments -