Ik heb een probleem met het via WCF doorgeven van een typed dataset. Ik heb het probleem zo bondig mogelijk samengevat; in realiteit is de code anders.
Ik heb een dataset met (onder meer) 2 tabellen, "Master" en "Detail". Beide worden gelezen van de database.
Tussen de twee tabellen ligt een relatie, zodat het verwijderen van records in de "Master" tabel ook records uit de "Detail" tabel zal schrappen.
Als de gebruiker z'n wijzigingen gaat bewaren, dan worden beide tabellen verwijderd en opnieuw ingevuld. In de database moet de oude data dus geschrapt worden, en de nieuwe data toegevoegd.
Daarna wordt de dataset via WCF naar de database server gestuurd om de data effectief te updaten. De DataContractSerializer loopt echter niet 100%.
Goed, het voorbeeldprogramma (Tot lijn 39 is het setup van de demo dataset) :
het resultaat hiervan is:
je ziet dat er dus een verschil is tussen beide datasets.
Mijn toegevoegd record van "Detail" is verdwenen!
het DiffGram van "DataSetDump.xml" ziet er als volgt uit:
Deze is dus wél correct, en toch loopt het deserializen mis.
Mijn idee is: DataContractSerializer.Deserialize() voegt eerst de "inserted" records toe. Daarna schrapt hij het gedelete record in "Master" waardoor hij, door de relatie, ook het pas toegevoegde record van de "Detail" schrapt, wat niet de bedoeling is.
Kern van het probleem is dus volgens mij dat ik bij het toevoegen van nieuwe records opnieuw dezelfde keys van de geschrapte records gebruik. Maar dat kan/mag ik niet veranderen (moet steeds met 1 beginnen).
Is heb er echter géén idee van hoe ik dit kan oplossen. Iemand?
Ik heb een dataset met (onder meer) 2 tabellen, "Master" en "Detail". Beide worden gelezen van de database.
Tussen de twee tabellen ligt een relatie, zodat het verwijderen van records in de "Master" tabel ook records uit de "Detail" tabel zal schrappen.
Als de gebruiker z'n wijzigingen gaat bewaren, dan worden beide tabellen verwijderd en opnieuw ingevuld. In de database moet de oude data dus geschrapt worden, en de nieuwe data toegevoegd.
Daarna wordt de dataset via WCF naar de database server gestuurd om de data effectief te updaten. De DataContractSerializer loopt echter niet 100%.
Goed, het voorbeeldprogramma (Tot lijn 39 is het setup van de demo dataset) :
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Runtime.Serialization; using System.IO; namespace DataSetProblem { class Program { static void Main(string[] args) { // Create dummy dataset DataTable Master = new DataTable("Master"); DataTable Detail = new DataTable("Detail"); Master.Columns.Add("MasterID", typeof(int)); Master.Columns.Add("Description", typeof(string)); Detail.Columns.Add("MasterID", typeof(int)); Detail.Columns.Add("DetailID", typeof(int)); Detail.Columns.Add("Description", typeof(string)); DataSet DemoDataSet = new DataSet("DemoDataSet"); DemoDataSet.Tables.Add(Master); DemoDataSet.Tables.Add(Detail); DemoDataSet.Relations.Add(new DataRelation("MasterDetail", Master.Columns["MasterID"], Detail.Columns["MasterID"])); // Fill with dummy data Master.Rows.Add(1, "Master line 1"); Detail.Rows.Add(1, 1, "Detail line 1"); DemoDataSet.AcceptChanges(); // Delete the data Master.Rows[0].Delete(); Master.Rows.Add(1, "New master line 1"); Detail.Rows.Add(1, 1, "New detail line 1"); // Serialize DumpDataSet(DemoDataSet); Console.WriteLine("Serializing..."); DataContractSerializer serializer = new DataContractSerializer(DemoDataSet.GetType()); using (Stream s = File.Create(@"c:\DataSetDump.xml")) { serializer.WriteObject(s, DemoDataSet); } // Deserialize Console.WriteLine("Deserializing..."); DataSet DemoDataSetDeserialized; using (Stream s = File.OpenRead(@"c:\DataSetDump.xml")) { DemoDataSetDeserialized = (DataSet) serializer.ReadObject(s); } DumpDataSet(DemoDataSetDeserialized); Console.ReadLine(); } public static void DumpDataSet(DataSet ds) { foreach (DataTable Table in ds.Tables) { int Total = Table.Rows.Count; int Deleted = Table.Select(null, null, DataViewRowState.Deleted).Length; int Added = Table.Select(null, null, DataViewRowState.Added).Length; Console.WriteLine("Table '{0}' : {1} total rows ({2} deleted, {3} added)", Table.TableName, Total, Deleted, Added); } } } } |
het resultaat hiervan is:
code:
1
2
3
4
5
6
| Table 'Master' : 2 total rows (1 deleted, 1 added) Table 'Detail' : 2 total rows (1 deleted, 1 added) Serializing... Deserializing... Table 'Master' : 2 total rows (1 deleted, 1 added) Table 'Detail' : 1 total rows (1 deleted, 0 added) |
je ziet dat er dus een verschil is tussen beide datasets.
Mijn toegevoegd record van "Detail" is verdwenen!
het DiffGram van "DataSetDump.xml" ziet er als volgt uit:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| <diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <DemoDataSet> <Master diffgr:id="Master2" msdata:rowOrder="1" diffgr:hasChanges="inserted"> <MasterID>1</MasterID> <Description>New master line 1</Description> </Master> <Detail diffgr:id="Detail2" msdata:rowOrder="1" diffgr:hasChanges="inserted"> <MasterID>1</MasterID> <DetailID>1</DetailID> <Description>New detail line 1</Description> </Detail> </DemoDataSet> <diffgr:before> <Master diffgr:id="Master1" msdata:rowOrder="0"> <MasterID>1</MasterID> <Description>Master line 1</Description> </Master> <Detail diffgr:id="Detail1" msdata:rowOrder="0"> <MasterID>1</MasterID> <DetailID>1</DetailID> <Description>Detail line 1</Description> </Detail> </diffgr:before> </diffgr:diffgram> |
Deze is dus wél correct, en toch loopt het deserializen mis.
Mijn idee is: DataContractSerializer.Deserialize() voegt eerst de "inserted" records toe. Daarna schrapt hij het gedelete record in "Master" waardoor hij, door de relatie, ook het pas toegevoegde record van de "Detail" schrapt, wat niet de bedoeling is.
Kern van het probleem is dus volgens mij dat ik bij het toevoegen van nieuwe records opnieuw dezelfde keys van de geschrapte records gebruik. Maar dat kan/mag ik niet veranderen (moet steeds met 1 beginnen).
Is heb er echter géén idee van hoe ik dit kan oplossen. Iemand?