Avatar billede CodingJoe Nybegynder
04. april 2013 - 00:38 Der er 17 kommentarer og
1 løsning

LINQ udfordringer ved nestede udtryk

Jeg har en collection, der hedder countries. I countries har jeg endnu en collection, der hedder cities.

Nu forsøger jeg at mappe disse to ting over i et andet min egen definition af countries og cities. Jeg gør fx.

var countries = context.countries.Select(x => new Country { Id = (long?)x.Id, Name = x.Name, Cities = new List<City>().Add(x.cities???)).ToList();

Jeg har forsøgt flere variationer, men får en masse fejl.
Er der een der kan fortælle mig, hvordan man gør det?
Avatar billede CodingJoe Nybegynder
04. april 2013 - 00:49 #1
Jeg kan sagtens mappe får countries til at virke, ved at lave new inde i mit linq udtryk. Dog er det cities, der driller en del. Jeg kan ikke få x.Cities over i Cities. Cities = x.cities.Select(c => new List<City>() ????
Avatar billede arne_v Ekspert
04. april 2013 - 04:21 #2
Til inspiration:

using System;
using System.Collections.Generic;
using System.Linq;

namespace E
{
    public class DBCity
    {
        public string Name { get; set; }
    }
    public class DBCountry
    {
        public string Name { get; set; }
        public List<DBCity> Cities { get; set; }
    }
    public class City
    {
        public string Name { get; set; }
    }
    public class Country
    {
        public string Name { get; set; }
        public List<City> Cities { get; set; }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            List<DBCountry> dblst = new List<DBCountry> { new DBCountry { Name = "Denmark",
                                                                          Cities = new List<DBCity> { new DBCity { Name = "Copenhagen" }, new DBCity { Name = "Aarhus" } } },
                                                          new DBCountry { Name = "Sweden",
                                                                          Cities = new List<DBCity> { new DBCity { Name = "Stockholm" }, new DBCity { Name = "Malmoe" } } } };
            foreach(DBCountry country in dblst)
            {
                Console.WriteLine(country.Name);
                foreach(DBCity city in country.Cities)
                {
                    Console.WriteLine("  " + city.Name);
                }
            }
            List<Country> lst = dblst.Select(c => new Country { Name = c.Name, Cities = c.Cities.Select(c2 => new City { Name = c2.Name }).ToList() }).ToList();
            foreach(Country country in lst)
            {
                Console.WriteLine(country.Name);
                foreach(City city in country.Cities)
                {
                    Console.WriteLine("  " + city.Name);
                }
            }
            Console.ReadKey();
        }
    }
}
Avatar billede platik Nybegynder
04. april 2013 - 07:52 #3
Et bud - uden at have testet:

var countries = context.countries.Select(x => new Country { Id = (long?)x.Id, Name = x.Name, Cities = x.cities.Select(city => new City { /* Set properties*/}).ToList()).ToList();
Avatar billede platik Nybegynder
04. april 2013 - 07:56 #4
Ah kan se arne_v gør det samme. Skulle måske have læst det hele først :). Jeg har også minimum glemt en "}"
Avatar billede CodingJoe Nybegynder
04. april 2013 - 08:10 #5
Ah, dvs man ikke kan angive en "var countries =", men skal explicit angive typen -> dvs. "List<Country> countries =".
Tror faktisk, jeg har haft dette problem før, men det blev lidt sent igår aftes.

Jeg prøver lige forslaget.
Avatar billede platik Nybegynder
04. april 2013 - 08:32 #6
Nah. Om du skriver "var" eller skriver typen giver samme resultat. Ved at angive typen er du bare sikker på det også er det du får retur. Ellers skal compileren nok brokke sig. Hvor ved "var" kunne du i princippet ende med en IEnumerable frem for en List (for lige at tage det som nok oftes sker).

Der er også lidt untagelser omkring implicit casts som kan ske hvis du angiver typen i stedet for at bruge var, men ikke noget der burde ske i denne sammenhæng.

Som du selv er inde på er det et nested udtryk. Derfor skal du også bruge en select inde i en select :-). Som ved den første select skal du også ved din "inner" select - selecte et "item" af gangen.
Avatar billede CodingJoe Nybegynder
04. april 2013 - 08:24 #7
Jeg får samme fejl:

LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[Entities.City] ToList[City](System.Collections.Generic.IEnumerable`1[Entities.City])' method, and this method cannot be translated into a store expression.

Jeg læste et sted at man ikke kan lave en 'ToList()' i en 'ToList()'. Det er et Linq udtryk jeg laver i forbindelse med Entity Framework 5.0. Helt sikkert det der driller.
Avatar billede CodingJoe Nybegynder
04. april 2013 - 08:43 #8
Ja, jeg har gjort det masser af gange før, uden at have problemer med nestede linq udtryk, men her tror jeg den ikke kan oversætte mit udtryk til en query imod min db. Er ret sikker på det er EF, der driller her...
Avatar billede platik Nybegynder
04. april 2013 - 09:03 #9
Jep, hvade jeg selv glemt.

Så bliver du nok nød til at dele den op i 2.

En hvor du selecter det du skal bruge og efterfølgende parser det over i dene egne objekter.

//Del1 hent hvad der skal bruges fra databasen til momory
var countries = context.countries.Select(x=> new {Id = (long?)x.Id, Name = x.Name, Cities = x.Cities}).ToList() //Husk at lave filter her inden tolist efter tolist ligger det hele i memory og er ikke længere en query der senere bliver eksekveret på databasen.

//Del2 Parse til egne objekter
.Select(x => new Country { Id = x.Id, Name = x.Name, Cities = x.Cities.Select(city => new City { /* Set properties*/}).ToList()}).ToList();


Igen overstående er ikke testet og kan sikkert også laves smartere, men lige den umiddelbare løsning jeg kan komme på.
Avatar billede CodingJoe Nybegynder
04. april 2013 - 10:19 #10
Det er lige præcis det, jeg ville undgå. Jeg har ingen problemer, når jeg deler mit udtryk i to.
Avatar billede platik Nybegynder
04. april 2013 - 10:54 #11
Så skal du prøve:

public class Country
    {

        public Country(IEnumerable<City> cities)
        {
            Cities = cities.ToList();
        }
        public string Name { get; set; }
        public List<City> Cities { get; set; }
    }

var countries = context.countries.Select(x => new Country(x.cities.Select(city => new City { /* Set properties*/})) { Id = (long?)x.Id, Name = x.Name}).ToList();

Det er lidt et skud. Ved at være længe siden jeg har arbejdet med EF og er ikke sikker på den går.


Eller bare ændre propertien fra list til enumerable hvis det er acceptabelt.
Avatar billede CodingJoe Nybegynder
04. april 2013 - 12:23 #12
Den konversion kan jeg vel også lave in-line?
Jeg prøver lige et par ting og vender fluks tilbage...
Avatar billede CodingJoe Nybegynder
04. april 2013 - 12:32 #13
Denne version virke, men giver mig kun een city i min cities collection:

List<Country> countries = context.countries.Select(x => new Country { Name = x.Name, Cities = new List<City> { x.cities.Select(c => new City { Id = c.Id, Name = c.Name }).FirstOrDefault() } }).ToList();
Avatar billede platik Nybegynder
04. april 2013 - 13:03 #14
Jes overstående selecter du alle cities men slutter med kun at tage den første. Du burde kunne smide din IEnumerable ind i din listes contructor i stedet:

List<Country> countries = context.countries.Select(x => new Country { Name = x.Name, Cities = new List<City>(x.cities.Select(c => new City { Id = c.Id, Name = c.Name })) }).ToList();
Avatar billede CodingJoe Nybegynder
04. april 2013 - 13:08 #15
Den har jeg prøvet. Jeg får følgende fejl:
Only parameterless constructors and initializers are supported in LINQ to Entities.
Avatar billede CodingJoe Nybegynder
04. april 2013 - 22:34 #16
Jeg fik det til at virke med følgende:
mycontext.countries.Select(x => new Country { Id = (long?)x.Id, Name = x.Name, Iso = x.ISO, Cities = x.cities.Select(c => new City{ Id = c.Id, Name = c.Name})}).ToList()
Avatar billede CodingJoe Nybegynder
04. maj 2013 - 20:02 #17
Jeg vil gerne lukke denne...kan I ikke smide et par svar ind, så jeg kan dele points.
Avatar billede arne_v Ekspert
05. maj 2013 - 02:01 #18
Jeg har ikke vaeret med i den sidste del.

Men:

dblst.Select(c => new Country { Name = c.Name, Cities = c.Cities.Select(c2 => new City { Name = c2.Name }).ToList() }).ToList()

og:

mycontext.countries.Select(x => new Country { Id = (long?)x.Id, Name = x.Name, Iso = x.ISO, Cities = x.cities.Select(c => new City{ Id = c.Id, Name = c.Name})}).ToList()

ser ens nok ud til at jeg toer smide et svar.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester