Avatar billede iwerksom Nybegynder
19. juni 2010 - 13:20 Der er 10 kommentarer og
1 løsning

Linq to Sql partial class return value?

Er i gang med at lære Linq to Sql

Jeg har bygget en række entities ved hjælp af Object relational designer.

Herefter har jeg lavet en partial class tblKatalog. De simple Select operationer går fint men jeg mangler forståelse for de lidt mere komplicerede som f.eks. denne:

public static IEnumerable<tblKatalog> SelectWhereID(int ID)
{
    DataClassesDataContext db = new DataClassesDataContext();
    var query = db.tblKatalogs
        .Where(m => m.ID == ID)
        .Select(m => new { m.ID, m.ISBN_ISSN });

}
Jeg kan via debug se at min var indeholder det jeg ønsker men hvordan skal jeg returnere min var?

På forhånd tak
Avatar billede arne_v Ekspert
19. juni 2010 - 20:18 #1
Virker:

return query;

ikke ?
Avatar billede Slettet bruger
19. juni 2010 - 22:31 #2
Nu kan det godt være jeg har misforstået hvad du gerne vil opnå... men:

Du leder efter en collection med samme primary-key?

Din var query - den kommer til at indeholde et object med to properties - hvordan hænger det sammen med din tblKatalog klasse - umiddelbart ville jeg tro, at du skulle instantiere nye tblKatalog instanser i din Select?
Avatar billede janus_007 Nybegynder
20. juni 2010 - 02:29 #3
Du kan ikke returnere en anonym type fra en funktion. Den findes jo kun som 'var'

Du kan gøre 2 ting, enten bare returnere som den er, altså:

public static IEnumerable<tblKatalog> SelectWhereID(int ID)
{
    DataClassesDataContext db = new DataClassesDataContext();
    return db.tblKatalogs
        .Where(m => m.ID == ID)
        .Select(m => m);

}
Forudsat et tblKatalog og tblKatalogs er samme type.

Du kan også.
public static IEnumerable<tblKatalog> SelectWhereID(int ID)
{
    DataClassesDataContext db = new DataClassesDataContext();
    return db.tblKatalogs
        .Where(m => m.ID == ID)
        .Select(m => new tblKatalog()
{
prop1 = m.propvalue1,
prop2 = m.propvalue2.... osv.
}
);

eller i ren query expression:

return db.tblKatalogs
        where m => m.ID == ID
        select new tblKatalog()
{
prop1 = m.propvalue1,
prop2 = m.propvalue2.... osv.
}
);

op til dig :)

husk desuden at smide en using omkring din context alså..
using(var db = new DataClassesDataContext())
{
    return db.tblKatalogs
        .Where(m => m.ID == ID)
        .Select(m => m);

}
Avatar billede iwerksom Nybegynder
21. juni 2010 - 14:45 #4
Tak for jeres besvarelser. Nu funker det næsten. Jeg prøver lige at forklare hvad jeg vil.
Jeg har som sagt brugt Object relational designer. Herefter har jeg lavet en partial class med følgende:

public partial class tblKatalog
{
#region Select methods
    public static IEnumerable<tblKatalog> Select()
    {
        /// <summary>
        /// Returns unsorted list of entity
        /// </summary>
        DataClassesDataContext db = new DataClassesDataContext();
        db.Log = new TraceWriter();
        return db.tblKatalogs;
    }

Herefter har jeg lavet metoder til pageing cacheing som beskrevet i ASP.NET 3.5 Unleashed.
Med jeres hjælp har jeg fået denne til at virke:

public static IEnumerable<tblKatalog> SelectWhereID(int ID)
{
    DataClassesDataContext db = new DataClassesDataContext();
   
        return db.tblKatalogs
        .Where(m => m.ID == ID)
        .Select(m => m); 
   
}

Men hvad gør jeg hvis jeg kun vil lave en Select på udvalgte columns?
Har prøvet følgende:
public static IEnumerable<tblKatalog> SelectShort()
{
    DataClassesDataContext db = new DataClassesDataContext();
    return db.tblKatalogs
        .Select(m => new tblKatalog()
        {
            ID = m.ID,
            Titel = m.Titel
        }
        );
 
 
}
Og får følgende fejl: Explicit construction of entity type 'tblKatalog' in query is not allowed.

Herefter prøvede jeg med en using:
public static IEnumerable<tblKatalog> SelectShort()
{
    using(var db = new DataClassesDataContext())
    return db.tblKatalogs
        .Select(m => new tblKatalog()
        {
            ID = m.ID,
            Titel = m.Titel
        }
        );
 
 
}
Og fik følgende fejl: Cannot access a disposed object.
Object name: 'DataContext accessed after Dispose.'.

Hvad gør jeg forkert?
Avatar billede janus_007 Nybegynder
21. juni 2010 - 21:06 #5
Lav en ToList() :) , du tilgår data contexten efter den har været åbnet.

using(var db = new DataClassesDataContext())
    return db.tblKatalogs
        .Select(m => new tblKatalog()
        {
            ID = m.ID,
            Titel = m.Titel
        }
        ).ToList();

Men i bund og grund er der jo ingen grund til at lave en metode, medmindre det naturligvis bare er for sjov eller fordi du skal følge nogle retningslinjer:

public IQueryable<tblKatalog> Query()
{
    using(var db = new DataClassesDataContext())
{
    return db.tblKatalogs;
       
}


Og så i din kaldende metode:

var result = YourService.Query().Where(x => x.Id == 123).ToList();

Så vil result være en List af typen tblKatalogs
Avatar billede iwerksom Nybegynder
22. juni 2010 - 10:26 #6
Tak for dit svar janus.
Har prøvet følgende men det virker stadig ikke.
public static IEnumerable<tblKatalog> SelectShort()
{
    using(var db = new DataClassesDataContext())
    return db.tblKatalogs
        .Select(m => new tblKatalog()
        {
            ID = m.ID,
            Titel = m.Titel
        }
        ).ToList();
 
 
}

Giver denne fejl: Explicit construction of entity type 'tblKatalog' in query is not allowed

Så det er galt er måske  at jeg forsøger at lave input seqencen om istedet for at lave en ny. Det burde jeg vel ikke med:
"m => new" ??

Jeg er meget åben overfor en anden måde at gøre det på. Eneste krav er en adskillelse fra præsentationslaget. Det har jeg som sagt løst ved ar lave partial classes i App_Code
Avatar billede janus_007 Nybegynder
23. juni 2010 - 23:21 #7
Hvis jeg lige laver et lille demoprojekt sp:
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var result = MyService.GetSome();
            var resultAnotherWay = MyService.GetSomeOnAnotherWay("XXX");

            var resultAnother = MyService.GetSomeMore().Where(m => m.CompanyName.StartsWith("A")).ToList();

           
        }
    }

    class MyService
    {
        public static IList<tEquity> GetSome() // funker fino :)
        {
            using (var context = new DataClasses1DataContext())
            {

                return context.tEquities.Select(
                    m => new tEquity()
                    {
                        CompanyName = m.CompanyName,
                        Currency = m.Currency
                    }
                    ).ToList();

            }

        }

        public static IList<tEquity> GetSomeOnAnotherWay(string isin) // funker fino :)
        {
            using (var context = new DataClasses1DataContext())
            {

                return context.tEquities.Where(m => m.ISIN == isin).ToList();


            }

        }


        public static IQueryable<tEquity> GetSomeMore()  //Dur ikke, cannot access disposed object.  (sorry my bad)
        {
            using (var context = new DataClasses1DataContext())
            {
                return context.tEquities;
            };
        }

    }
}


Så jeg forstår ikke hvad din tblKatalog er for en størrelse? Den object relationelle designer, hvad er det for en?
Avatar billede iwerksom Nybegynder
24. juni 2010 - 11:46 #8
Hej janus tak for din vedholdenhed. Det betyder meghet for mig at få løst dette problem hurtigst muligt.

Object relational designer er et grafisk værktøj i Visual Studio. Det er til os som ikke bygger alle vores entities og deres relations i hånden.
Designeren generere en strongly typed DataContext class.
Min database tabel tblKatalog bliver exposed af DataContext som en strongly typed property.

Designeren generere også en distinct class for hver databasetabel i dette tilfælde tblKatalog

Her er et uddrag af koden som genereres:

public System.Data.Linq.Table<tblKatalog> tblKatalogs
    {
        get
        {
            return this.GetTable<tblKatalog>();
        }
    }

[Table(Name="dbo.tblKatalog")]
public partial class tblKatalog : INotifyPropertyChanging, INotifyPropertyChanged
{
   
    private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
   
    private int _ID;
    private string _ISBN_ISSN;   
    private string _Serie;   
    private string _Forlag;
        private string _Titel;

....
Herefter følger en masse metoder til relationerne til andre tabeller og datachanging events.

Og det er jo altsammen meget fint men ikke når jeg ikke kan arbejde med det og udvælge enkelte columns. Der er jo ingen grund til SELECT * når jeg kun skal bruge ID, ISBN og Titel.
Jeg vil ikke have linq to sql kode i mine asp.net filer og har derfor oprettet partial classes og bruger  objectdatasource til at repræsentere mine classes.

En alternativ løsning på problemet kunne være at jeg laver min egen datashape som kun indeholder columns jeg skal bruge.
Avatar billede janus_007 Nybegynder
24. juni 2010 - 19:42 #9
Hej...

Så kender jeg den fint, det er også den jeg selv sidder med, jeg oplever dog ikke de problemer du har.

Gad vide om det kan skyldes VS, jeg sidder med VS2008 og VS2010, begge fungerer som de skal.

Jeg har dog lavet demoen der i VS2010, vil du have den?
Avatar billede iwerksom Nybegynder
25. juni 2010 - 11:11 #10
Hej Igen
Jeg sidder med Visual Studio 2008.
Vil meget gerne have din demo. Gerne med eksempel på hvordan du vælger enkelte columns.
Tak igen - jeg har været inde på din profil og kontakter dig.
Avatar billede iwerksom Nybegynder
16. januar 2011 - 20:58 #11
Hej igen. Nu har jeg endelig fundet svaret på mit spørgsmål. Så jeg synes lige jeg ville give det her hvis der nu er andre som læser ASP.NET Unleashed og bøvler med det samme.
Som med alle gode løsninger er det meget simpelt.
Her er den originale kode:
public static IEnumerable<tblKatalog> SelectWhereID(int ID)
{
    DataClassesDataContext db = new DataClassesDataContext();
    var query = db.tblKatalogs
        .Where(m => m.ID == ID)
        .Select(m => new { m.ID, m.ISBN_ISSN });

}

Eftersom en Select laver en nye anonym type er løsningen:

public static IEnumerable SelectWhereID(int ID)
{
    DataClassesDataContext db = new DataClassesDataContext();
    return db.tblKatalogs
        .Where(m => m.ID == ID)
        .Select(m => new { m.ID, m.ISBN_ISSN });

}

Det jeg ikke havde fattet var at eftersom typen er anonym skal der ikke være en <class> efter IEnumerable.
Ak ja så simpelt kan det være. Endnu engang tak til dem som hjalp mig på vej
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