Avatar billede superzapper Nybegynder
15. januar 2006 - 20:56 Der er 26 kommentarer og
1 løsning

ObjectDataSource Update

Hejsa derude.

Jeg har rodet med en side hvor jeg har et detailsview der "bliver fodret" af en ObjectDataSource kontrol. Jeg kan bare ikke få det til at virke med opdateringer via ObjectDataSourcen. Så snart jeg har sat "update method" får jeg følgende exception:

No parameterless constructor defined for this object.
Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.

Er der nogen der ved hvad der er galt? Jeg er ikke med på hvad det er for en constructor der skulle give problemer?
Avatar billede snepnet Nybegynder
15. januar 2006 - 20:59 #1
du skal angive en default constructor på din klasse.

hvis du har en klasse

public class Test
{
  // så ser din default/tomme constructor sådan her ud
  public Test()
  {
  }
}

mvh
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:00 #2
det er fordi din datasourcecontrol instantierer dine klasser ved blot at lave en new på typen - uden parametre:

Test instanse = new Test();

hvorefter den sætter dine properties (som altså skal være read/write) på instansen.

mvh
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:02 #3
hvis du slet ikke har nogle constructors på din klasse for du automatisk oprettet en default - så fejlen kommer fordi du selv har angivet andre constructors - der tager parametre.
f.eks.

public Test(string someMessage)
{
  ..
}

mvh
Avatar billede superzapper Nybegynder
15. januar 2006 - 21:02 #4
Klassen har en constructor:
public class SortBusiness
{
    public SortBusiness()
    {
       
    }

efterfulgt af metoder... Så det burde ikke være derfor...
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:04 #5
hvad returnerer du fra den metode du bruger som selectmethod?
mvh
Avatar billede superzapper Nybegynder
15. januar 2006 - 21:05 #6
Et strongly typed dataset..
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:07 #7
hvilken funtion har din SourtBusiness klasse?
mvh
Avatar billede superzapper Nybegynder
15. januar 2006 - 21:08 #8
public SortDataSet GetSortList()
    {
        return SortDAO.GetSortList();
    }

Som bare kalder en klasse der trækker datasettet via den autogenererede adapter..

public static SortDataSet GetSortList()
    {
        SortDataSet sortDataset = new SortDataSet();

        SortDataTableTableAdapter sortAdapter = new SortDataTableTableAdapter();

        sortAdapter.Fill(sortDataset.SortDataTable);

        return sortDataset;
    }
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:09 #9
(din object datasource skal kunne tale indholdet af en række i dit grid, og udfra værdierne i den, skal den kunne instantiere en forekomst af den type som er brugt som datagrundlag for rækken).
mvh
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:11 #10
ikke "kunne tale indholdet" .... kunne TAGE indholdet :o)
mvh
Avatar billede superzapper Nybegynder
15. januar 2006 - 21:13 #11
Ok, men hvordan vil man så typisk gøre hvis man skal bruge et strongly typed dataset som skal bindes til et gridview og man skal kunne lave updates?! Hvilket objekt vil du sende til din select og hvad vil du tage imod i update?
Avatar billede superzapper Nybegynder
15. januar 2006 - 21:23 #12
Er det bare generelt noget lort at bruge strongly typed dataset??
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:38 #13
bruger normalt egne typer/collections sammen med objectdatasource, men det du laver skulle meget gerne kunne lade sig gøre uden de store fiksfakserier.

prøv at se om der er noget der springer i øjnene her:

http://msdn.microsoft.com/msdnmag/issues/05/01/DataPoints/default.aspx

mvh
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:39 #14
Generelt noget lort ... :o) ... det er der mange der har en holdning til, men der er jo fordele og ulemper ved alt ;o)
Avatar billede superzapper Nybegynder
15. januar 2006 - 21:47 #15
Ok. Jeg var bare vild med ideen med at man kunne autogenerere en klasse til at holde ens data ud fra en sql sætning, som så samtidig er serializable uden man selv skal bakse med den. Men det kan godt være jeg skal holde mig til selv at labe nogen data transfer objekter..
Avatar billede snepnet Nybegynder
15. januar 2006 - 21:51 #16
er det bare data du haler op fra en sql-server?
mvh
Avatar billede superzapper Nybegynder
15. januar 2006 - 22:02 #17
Jepper.. Du har måske en anden ide?
Avatar billede snepnet Nybegynder
15. januar 2006 - 22:08 #18
så kan du bare trække tabellen ind i designeren.... så får du en sqldatasource der intert arbejder med datasets, hvilket bevirker at du kan indsætte, slette, opdatere og page uden kode.
mvh
Avatar billede snepnet Nybegynder
15. januar 2006 - 22:10 #19
(og du kan få oprettet de respektive sql-statemenst udfra en select, og også få dem lagt ned som stored procedures hvis du kan lide den slags).
mvh
Avatar billede superzapper Nybegynder
15. januar 2006 - 22:10 #20
Ok, det kan da være jeg lige skal kigge på det. Men tror i sidste ende jeg går tilbage til at lave nogle "dumme" objekter der holder data og så læser jeg ud med en datareader - det er nok det bedste på sigt...
Avatar billede snepnet Nybegynder
15. januar 2006 - 22:13 #21
en klar objektmodel i applikationen, hvor man også har lidt mere frihed til at definere sine egne typer (end man har hvis man benytter strongly typed datasets) er jo heller ikke at kimse af ;o)

men ... den deklarative model omkring administration af almindelige stamdata, opsætning eller lignende er klaret på 20 sekunder med en sqldatasource og en wizard..... også noget der er mange der har lidt holdninger til ;o)

mvh
Avatar billede superzapper Nybegynder
15. januar 2006 - 22:20 #22
Ja, men jeg må nu nok tilstå at jeg hellere vil lave noget kram der kan udbygges end at lave noget hurtigt juks jeg ikke selv har kontrol over..

Jeg takker for hjælpen. Bare smid et svar hvis du vil have nogen points..
Avatar billede snepnet Nybegynder
15. januar 2006 - 22:25 #23
ja - det giver normalt det bedste resultat, og der er da en del hjælp at hente med generics i den forbindelse synes jeg.... det med at lave de typestærke lister er jo så en foræring.
der er dog så nogle forhold der skal være på plads på de typer du benytter i de lister du databinder til (hvis du vil kunne opdatere og den slags) - sig til hvis du får bøvl med det.... der er nogle småting man lige skal være bekendt med. f.eks. hvilke krav der er til klasserne hvis sortering skal virke og den slags.
mvh
Avatar billede superzapper Nybegynder
15. januar 2006 - 22:42 #24
Jeg vil meget gerne høre om det med sortering med det samme for det kommer jeg til at skulle bruge inden så længe...
Avatar billede snepnet Nybegynder
16. januar 2006 - 03:15 #25
ok... det er ikke så kompliceret, men på det lidt "løst i fugerne" (stringbased).

hvis du har et grid med boundfield:
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />

så kan du på feltet angive et SortExpression. dette udtryk sørger din datasourcecontrol internt for bliver benyttet som parameter på din selectmetode, hvilket så kræver at du har en sådan metode.

på din objectdatasource kan du have angivet en selectmetode sådan her:
SelectMethod="GetAllPersons"

og et SortParameterName
SortParameterName="sortExpression"

i dette tilfælde undlader vi selectparametre, så GetAllPersons() er så parameterfri, men da jeg har angivet sortExpressions på feltet og et SortParameterName på objectdatasource giver det, at jeg på den klasse hvor GetAllPersons er implementeret - givet ved
TypeName="SampleData.PersonAccess" på objectdatasource

skal have metoden:
GetAllPerson(string sortExpression)

som så bliver kaldt i forbindelse med sortering.

i dette tilfælde vil udtrykket kunne have 2 forskellige værdier:
"Name"
og
"Name desc"

så du skal altså selv - i GetAllPersons(string sortExpression) sørger for at finde ud af om det er desc ved at kigge på den parameter du får med.

det er så ikke specielt kompliceret at lave selve sorteringen... det kan du gøre på flere måder, afhængigt af hvad det er for en collection du returnerer.

hvis vi siger at du (og det er en anbefaling) benytter generics, vil GetAllPerson(string sortExpression) så have en signatur som denne:

public List<Person> GetAllPersons(string sortExpression)

og hvis du vil lave en lidt mere generisk løsning af det - kunne du implementere den som noget i denne stil:

public List<Person> GetAllPersons(string sortExpression)
{
    List<Person> persons = SomeDBAccessLayer.GetPersons();
    if (sortExpression == String.Empty)
    {
        return persons;
    }

    string orgSortExpression = sortExpression.ToLower();
    string strippedSortExpression = orgSortExpression.Replace(" desc", String.Empty);

    Persons.Sort(delegate(Person p1, Person p2)
        {
            PropertyDescriptor xproperty = TypeDescriptor.GetProperties(p1).Find(strippedSortExpression, true);
            PropertyDescriptor yproperty = TypeDescriptor.GetProperties(p2).Find(strippedSortExpression, true);

            IComparable xcomp = xproperty.GetValue(p1) as IComparable;
            IComparable ycomp = xproperty.GetValue(p2) as IComparable;

            if (orgSortExpression.Contains(" desc"))
                return ycomp.CompareTo(xcomp);
            else
                return xcomp.CompareTo(ycomp);                   

        });
    return persons;
}

nu er det jo ikke den mest økonomiske implementering (reflection mv), og der er flere måder det kan knække på... men til gengæld kan den sortere hvad som helst, så længe dine sortExpressions matcher dine properties (hvilket jo sådan set også er meget naturligt :o).

... du kan jo evt. udvide med sådan noget som dette her:

Debug.Assert(xproperty != null);
Debug.Assert(yproperty != null);

og

Debug.Assert(x != null);
Debug.Assert(y != null);

du kan også lave dig en Person-Comparer implementering istedet, hvis du bedre kan lide det... det kunne du gøre sådan her (det er jo det samme kode):

public class PersonComparer : IComparer<Person>
{
    private string _sortExpression = <someDefault>;

    public PersonComparer(string sortExpression)
    {
        if(sortExpression != String.Empty)
        {
            _sortExpression = sortExpression.ToLower();
        }
    }

    public int Compare(Person x, Person y)
    {
        string strippedSortExpression = _sortExpression.Replace(" desc", String.Empty);
       
        PropertyDescriptor xproperty = TypeDescriptor.GetProperties(x).Find(strippedSortExpression, true);
        PropertyDescriptor yproperty = TypeDescriptor.GetProperties(y).Find(strippedSortExpression, true);

        Debug.Assert(xproperty != null);
        Debug.Assert(yproperty != null);

        IComparable xcomp = xproperty.GetValue(x) as IComparable;
        IComparable ycomp = xproperty.GetValue(y) as IComparable;

        Debug.Assert(x != null);
        Debug.Assert(y != null);

        if(_sortExpression.Contains(" desc"))
            return ycomp.CompareTo(xcomp);
        else
            return xcomp.CompareTo(ycomp);                   
    }
}

så kunne du implementere den oprindelige metode sådan her istedet:

public List<Person> GetAllPersons(string sortExpression)
{
    List<Person> persons = SomeDBAccessLayer.GetPersons();
    persons.Sort(new PersonComparer(sortExpression));
    return Persons;
}

... så er alt fnidderfnadderet pakket ind i din comparer istedet.

nu er ovenstående så specifikt på sammenligning af instanser af Person, men du kan relativt let skrive det om til en generisk sorteringscomparer, som så kan sortere hvad som helst:

public class Sorter<T> : Comparer<T>
{
    private string _sortExpression = String.Empty;

    public Sorter(string sortExpression)
    {
        if(sortExpression != String.Empty)
        {
            _sortExpression = sortExpression.ToLower();
        }
    }

    public override int Compare(T x, T y)
    {
        // ingen sortering, hvis vi ikke har noget udtryk
        if (_sortExpression == String.Empty)
            return 0;
       
        string strippedSortExpression = _sortExpression.Replace(" desc", String.Empty);

        PropertyDescriptor xproperty = TypeDescriptor.GetProperties(x).Find(strippedSortExpression, true);
        PropertyDescriptor yproperty = TypeDescriptor.GetProperties(y).Find(strippedSortExpression, true);

        Debug.Assert(xproperty != null);
        Debug.Assert(yproperty != null);

        IComparable xcomp = xproperty.GetValue(x) as IComparable;
        IComparable ycomp = xproperty.GetValue(y) as IComparable;

        Debug.Assert(x != null);
        Debug.Assert(y != null);

        if (_sortExpression.Contains(" desc"))
            return ycomp.CompareTo(xcomp);
        else
            return xcomp.CompareTo(ycomp);                   
    }
}

som du så kan bruge sådan her:

public List<Person> GetAllPersons(string sortExpression)
{
    List<Person> persons = SomeDBAccessLayer.GetPersons();
    Persons.Sort(new Sorter<Person>(sortExpression));
    return Persons;
}

eller sådan her:
public List<Car> GetAllCars(string sortExpression)
{
    List<Car> cars = SomeDBAccessLayer.GetCars();
    cars.Sort(new Sorter<Car>(sortExpression));
    return cars;
}

osv...

det er en måde at gøre det ... men bestemt ikke den eneste.

mvh
Avatar billede superzapper Nybegynder
16. januar 2006 - 07:59 #26
Ok, så er jeg med. Jeg regner med at prøve at implementere det inden alt for længe, men det er til et fritidsprojekt så det er lidt an på tiden. Endnu engang tak for hjælpen...
Avatar billede snepnet Nybegynder
16. januar 2006 - 08:06 #27
det var så lidt :o)
mvh
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