Avatar billede baitianlong Nybegynder
24. april 2005 - 23:29 Der er 23 kommentarer og
1 løsning

Persistens / gem og hent data

Hvordan laver man på enkel vis persistens i C#. Jeg har prøvet det i Java med serializable, og husker at man kunne gemme ens Model i en fil ret let. Hvad gør man i C#?

Det drejer sig om een collection klasse (AftaleBog) som indeholder en anden klasse (Aftale) og så er der to forms. Mere er der ikke :)
Avatar billede arne_v Ekspert
24. april 2005 - 23:33 #1
I C# kan du ligesom i Java både serialisere binært og til XML !
Avatar billede arne_v Ekspert
24. april 2005 - 23:34 #2
Eksempel:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class X
{
    private int v;
    public int V
    {
        get
        {
            return v;
        }
        set
        {
            v = value;
        }
    }

}

class MainClass
{
    public static byte[] Object2ByteArray(Object o)
    {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, o);
        return ms.ToArray();
    }
    public static object ByteArray2Object(byte[] theByteArray)
    {
        MemoryStream ms = new MemoryStream(theByteArray);
        BinaryFormatter bf = new BinaryFormatter();
        ms.Position = 0;
        return bf.Deserialize(ms);
    }
    public static void Main(string[] args)
    {
        X x1 = new X();
        x1.V = 123;
        Console.WriteLine(x1.V);
        byte[] b = Object2ByteArray(x1);
        X x2 = (X)ByteArray2Object(b);
        Console.WriteLine(x2.V);
    }
}
Avatar billede arne_v Ekspert
24. april 2005 - 23:34 #3
Eksempel:

using System;
using System.IO;
using System.Xml.Serialization;

public struct Test
{
    public int a;
    public double b;
    public string c;
}

class MainClass
{
    public static void Main(string[] args)
    {
        Test tst;
        tst.a = 123;
        tst.b = 123.456;
        tst.c = "ABC";
        XmlSerializer ser = new XmlSerializer(typeof(Test));
        StreamWriter sw = new StreamWriter("C:\\test.xml");
        ser.Serialize(sw, tst);
        sw.Close();
        StreamReader sr = new StreamReader("C:\\test.xml");
        Test tst2 = (Test)ser.Deserialize(sr);
        sr.Close();   
        Console.WriteLine(tst2.a + " " + tst2.b + " " + tst2.c);
    }
}
Avatar billede baitianlong Nybegynder
24. april 2005 - 23:39 #4
Jeg er mest til den sidste :) Det er vel min aftalebog, der skal gemmes? Kan du hjælpe med at putte det ind. Skal vi ikke lave en metode deri som gemmer, og en der henter ved opstart. Der er kun det her nu...

using System;
using System.Collections;

namespace Calendar
{
    public class AftaleBog
    {
        private ArrayList aftaler;

        public AftaleBog()
        {
            aftaler = new ArrayList();
        }

        public void AddAftale(Aftale a)

        public void RemoveAftale(Aftale a)

        public ArrayList GetAftaler(DateTime tid)
    }
}

:)
Avatar billede arne_v Ekspert
24. april 2005 - 23:43 #5
XmlSerializer ser = new XmlSerializer(typeof(Calendar.AftaleBog));
StreamWriter sw = new StreamWriter("aftalebog.xml");
ser.Serialize(sw, dinaftalebog);
sw.Close();

og

XmlSerializer ser = new XmlSerializer(typeof(Calendar.AftaleBog));
StreamReader sr = new StreamReader("aftalebog.xml");
dinaftalebog = (Calendar.AftaleBog)ser.Deserialize(sr);
sr.Close(); 

og så skal du lige finde ud af om den klasse serialiserer godt, men det
finder du ud af med try and error metode
Avatar billede baitianlong Nybegynder
24. april 2005 - 23:55 #6
Jeg har smidt det i constructoren og på en knap.

Der bliver lavet en xml fil, men dataen gemmes ikke. Aftalebogen er tom ved opstart.

Der står kun dette i xml filen:

<?xml version="1.0" encoding="utf-8"?>
<AftaleBog xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

Ellers er det stilet nok. Kan du hjælpe med resten.

public KalenderForm(AftaleBog abog)
{
    this.abog = abog;
    dato = new DateTime();
    InitializeComponent();
    monthCalendar1_DateChanged(null, null);
    XmlSerializer ser = new XmlSerializer(typeof(Calendar.AftaleBog));
    StreamWriter sw = new StreamWriter("c:\\aftalebog.xml");
    ser.Serialize(sw, abog);
    sw.Close();
}

------------

private void button5_Click(object sender, System.EventArgs e)
{
    XmlSerializer ser = new XmlSerializer(typeof(Calendar.AftaleBog));
    StreamWriter sw = new StreamWriter("c:\\aftalebog.xml");
    ser.Serialize(sw, abog);
    sw.Close();
    Dispose();
}

:)
Avatar billede baitianlong Nybegynder
25. april 2005 - 00:02 #7
ok, jeg kan godt se jeg har kopieret lidt dårligt:

Jeg har prøvet med:

static void Main()
{
    XmlSerializer ser = new XmlSerializer(typeof(Calendar.AftaleBog));
    StreamReader sr = new StreamReader("aftalebog.xml");
    AftaleBog abog = (Calendar.AftaleBog)ser.Deserialize(sr);
    sr.Close();
    Application.Run(new KalenderForm(abog));
}

------->

public KalenderForm(AftaleBog abog)
{
    this.abog = abog;
    dato = new DateTime();
    InitializeComponent();
    monthCalendar1_DateChanged(null, null);
}

-------  og...

private void button5_Click(object sender, System.EventArgs e)
{
    XmlSerializer ser = new XmlSerializer(typeof(Calendar.AftaleBog));
    StreamWriter sw = new StreamWriter("c:\\aftalebog.xml");
    ser.Serialize(sw, abog);
    sw.Close();
    Dispose();
}

Men stadig ikke data
Avatar billede arne_v Ekspert
25. april 2005 - 00:09 #8
Prøv lige og tilføj en public property for aftaler
Avatar billede lifo Nybegynder
25. april 2005 - 00:12 #9
pas på med StreamReader("aftalebog.xml");
tror at den tager den mappe som programmet kører fra
nok en eller anden temp mappe
Avatar billede baitianlong Nybegynder
25. april 2005 - 00:17 #10
Jeg har skiftet til C:\\ og filen ligger fint der.

Men den skriver ikke Aftalerne deri.

Jeg ved ikke hvad du mener med "Prøv lige og tilføj en public property for aftaler"
Avatar billede baitianlong Nybegynder
25. april 2005 - 00:19 #11
Jeg kan se for hver gang jeg kører programmet at xml filen bliver udskiftet/opdateret på dens tidspunkt, men der er bare ikke indhold i... :)
Avatar billede arne_v Ekspert
25. april 2005 - 00:20 #12
Eksempel:

using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Xml.Serialization;

public class Test
{
    private ArrayList list;
    public Test()
    {
        list = new ArrayList();
    }
    public void Add(string s)
    {
        list.Add(s);
    }
    public ArrayList List
    {
        get
        {
            return list;
        }
        set
        {
            list = value;
        }
    }
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder("");
        for(int i = 0; i < list.Count; i++)
        {
            sb.Append(list[i]);
        }
        return sb.ToString();
    }
}

class MainClass
{
    public static void Main(string[] args)
    {
        Test tst = new Test();
        tst.Add("a");
        tst.Add("bb");
        tst.Add("ccc");
        Console.WriteLine(tst);
        XmlSerializer ser = new XmlSerializer(typeof(Test));
        StreamWriter sw = new StreamWriter("C:\\test.xml");
        ser.Serialize(sw, tst);
        sw.Close();
        StreamReader sr = new StreamReader("C:\\test.xml");
        Test tst2 = (Test)ser.Deserialize(sr);
        sr.Close(); 
        Console.WriteLine(tst2);
    }
}
Avatar billede arne_v Ekspert
25. april 2005 - 00:21 #13
public class Test
{
    private ArrayList list; // <---- private field
    ...
    public ArrayList List // <---- public property
    {
        get
        {
            return list;
        }
        set
        {
            list = value;
        }
    }
    ...
}
Avatar billede baitianlong Nybegynder
25. april 2005 - 00:30 #14
Det begynder vist at hjælpe på det. Den prøver at loade, men siger der er fejl i xml dokumentet. Så slettede jeg det, og så sagde den det manglede, så oprettede jeg en tom tekstfil med filnavnet, og igen fejl i xml dokumentet.
Avatar billede arne_v Ekspert
25. april 2005 - 00:32 #15
Du skal nok lige have startet op.

Prøv og ændre koden til at køre videre selv filen ikke er der, lslet filen,
start programet, gem, ud og start igen.
Avatar billede arne_v Ekspert
25. april 2005 - 00:33 #16
Du kan enten teste på om filen erder eller bare smække en try catch på.
Avatar billede baitianlong Nybegynder
25. april 2005 - 00:41 #17
System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type Calendar.Aftale was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
Avatar billede baitianlong Nybegynder
25. april 2005 - 00:43 #18
Det var efter slette fil -> starte program -> lave to aftaler -> lukke program :)
Avatar billede baitianlong Nybegynder
25. april 2005 - 00:52 #19
Nå jeg troede lige jeg var klog og kunne:

[STAThread]
[XmlInclude(typeof(AftaleBog)), XmlInclude(typeof(Aftale))]

men det var den ligeglad med.
Avatar billede baitianlong Nybegynder
25. april 2005 - 00:59 #20
Det er ved at være lidt langhåret. Men jeg vil gerne se det virke. Har du et bud på en løsning ? Jeg vil gerne sende filer, give max points og alt det der :) Jeg tror ikke det er særlig langt fra.
Avatar billede arne_v Ekspert
25. april 2005 - 07:35 #21
nyt eksempel:

using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Xml.Serialization;

public class X
{
    private int v;
    public X() : this(0)
    {
    }
    public X(int v)
    {
        this.v = v;
    }
    public int V
    {
        get
        {
            return v;
        }
        set
        {
            v = value;
        }
    }
    public override string ToString()
    {
        return v.ToString();
    }
}

[XmlInclude(typeof( X ))]
public class Test
{
    private ArrayList list;
    public Test()
    {
        list = new ArrayList();
    }
    public void Add(X x)
    {
        list.Add(x);
    }
    public ArrayList List
    {
        get
        {
            return list;
        }
        set
        {
            list = value;
        }
    }
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder("");
        for(int i = 0; i < list.Count; i++)
        {
            sb.Append(list[i]);
        }
        return sb.ToString();
    }
}

class MainClass
{
    public static void Main(string[] args)
    {
        Test tst = new Test();
        tst.Add(new X(1));
        tst.Add(new X(2));
        tst.Add(new X(3));
        Console.WriteLine(tst);
        XmlSerializer ser = new XmlSerializer(typeof(Test));
        StreamWriter sw = new StreamWriter("C:\\test.xml");
        ser.Serialize(sw, tst);
        sw.Close();
        StreamReader sr = new StreamReader("C:\\test.xml");
        Test tst2 = (Test)ser.Deserialize(sr);
        sr.Close(); 
        Console.WriteLine(tst2);
    }
}
Avatar billede arne_v Ekspert
25. april 2005 - 07:36 #22
Din AftaleBog klasse skal altså have en

[XmlInclude(typeof(Aftale))]

på sig.
Avatar billede baitianlong Nybegynder
25. april 2005 - 18:42 #23
Tja, og det var alt der skulle til med det jeg havde nu.

[XmlInclude(typeof( Aftale ))]
public class AftaleBog
{
    public ArrayList aftaler;

Så kører det. Tak for hjælpen. :)
Avatar billede arne_v Ekspert
25. april 2005 - 18:44 #24
så vil jeg ligge 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