I am trying to create a simple POC so that we can decide if we can move forward replacing our DataAbstract server in Delphi with a C# version, while keeping (or the time being) our clients in Delphi.
On the server side we have this relatively simple piece of code that deals wit database changes and is called from a TDARemoteDataAdapter. I tried to convert this to C# code, couldn’t find a fast way to do this and I couldn’t find any examples.
I would appreciate some help…
regards
Paul Sjoerdsma
function TPSPUserDataBroker.UpdateData(const Delta: Binary): Binary;
var
updateDelta : IDADelta;
tableName : string;
begin
result := Nil;
DataStreamer2.Initialize(Delta, aiReadFromBeginning);
// Check if we need to do anything
if DataStreamer2.DeltaCount = 0 then
begin
Exit;
end;
tableName := ......
updateDelta := NewDelta(tableName);
DataStreamer2.ReadDelta(DataStreamer2.DeltaNames[0] , updateDelta);
DataStreamer2.Finalize;
try
try
// Process delta internally
.........
updateDelta.Changes[0].Status := csResolved;
except
updateDelta.Changes[0].Status := csFailed;
raise;
end; // try-except
finally
result := Binary.Create;
DataStreamer2.Initialize(result, aiWrite);
DataStreamer2.WriteDelta(updateDelta);
DataStreamer2.Finalize;
end; // try-finally
end;
public override Binary UpdateData(Binary serializedDelta)
{
this.CheckConnection();
// Load deltas from incoming stream
var deltas = this.DeserializeDeltas(serializedDelta);
if (deltas.Count == 0)
{
return null;
}
// ???
// Serialize deltas and send them back to the client (used to report failed updates and/or provide server-calculated field values)
return this.SerializeDeltas(deltas);
}
That seems to be happening a lot lately, people not understanding what I am asking
I’ll try to explain
The logic in Delphi is from our current Delphi application server. This is the call that is tied to the TDARemoteDataAdapter on our Delphi client and basically sends the changes made to a table from the client to our application server.
To be clear, our underlying database is dynamic, so we do not know in advance what tables a customer has in the database, or what fields are defined in each table. However the application server has access to “metadata” which describes the customer database.ZSo we need to manually process eacg change, check business logic and apply the changes or refuse them.
So what happens next basically is that we
extract the change --> updateDelta
Process the change
Set the status to either csResolved or csFailed
Write back the result
So what I am looking for is C# code that does rougly the same,
internal Binary UpdateData(Binary delta, string tableName)
{
using (DataStreamer streamer = new Bin2DataStreamer())
{
streamer.InitializeStreamer(delta, StreamerInitialization.ReadFromBeginning);
}
}
This is what my initial attempt looked like, but how do I extract the Delta from the Binary passed?
This is the area where a single word can change things from “very easy to do” to “no, that’s not possible, sorry” and vice versa. So it is always better to ask again.
Yes, it helps a lot.
So, as far as I understand the service you are developing doesn’t inherit from the base DataAbstract service.
So the reader/writer code would look like
public IList<Delta> DeserializeDelta(Binary serializedDelta)
{
var deltas = new List<Delta>();
var streamer = new Bin2DataStreamer();
try
{
streamer.InitializeStreamer(serializedDelta, StreamerInitialization.ReadFromBeginning);
foreach (var element in streamer.Elements.Values)
{
if (element.ElementType != StreamElementType.Delta)
{
continue;
}
var schemaTable = new SchemaDataTable(element.Name); // Better to cache this
var delta = new Delta(schemaTable);
streamer.ReadDelta(delta);
deltas.Add(delta);
}
}
finally
{
streamer.FinalizeStreamer();
}
return deltas;
}
public Binary SerializeDelta(IList<Delta> deltas)
{
var serializedDeltas = new Binary();
var streamer = new Bin2DataStreamer();
try
{
foreach (var delta in deltas)
{
streamer.WriteDelta(delta);
}
}
finally
{
streamer.FinalizeStreamer();
}
return serializedDeltas;
}
var schemaTable = new SchemaDataTable(element.Name); // Better to cache this
with code that somehow obtains correct SchemaDataTable instance containing proper field definitions (ie field names and types should match ones passed via Delta). Thing is that .ReadDelta not only deserializes Delta from a stream but also validates deserialized Delta against provided Schema Table.
EDIT: If you cannot provide that SchemaDataTable instance (f.e. Delta you need to process doesn’t match to any of the Schema tables) then a custom Delta reader method can be implemented. In that case send a mail to support@ and I’ll create a code sample for you.