Convert Delphi standard "UpdateData" to C#


(Paul Sjoerdsma) #1

Hi,

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;


(Paul Sjoerdsma) #3

Almost 2 days since I posted this question. Either it is not possible to find the equivalent C# approach or this question was overlooked…

regards
Paul


(antonk) #4

It is not exactly clear what you are asking.

In general the code you want might look like

	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);
	}

(Paul Sjoerdsma) #5

That seems to be happening a lot lately, people not understanding what I am asking :grinning:
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?

Does this help to clarify my original question?

regards
Paul


(antonk) #6

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;
	}

(Paul Sjoerdsma) #7

Thanks for the example code!

When I update a singek field from the client side and the change is posted. I get the following exception

"An exception of type ‘RemObjects.DataAbstract.DAException’ occurred in RemObjects.DataAbstract.dll but was not handled in user code

Additional information: Some fields in delta do not exists in the table or are not updatable."

It happens on this line
–>streamer.ReadDelta(delta);

Any ideas what I am missing?
If necessary I can update a very simple poc project that I am using,

regards
Paul


(antonk) #8

You have to replace this line

			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.


(Paul Sjoerdsma) #9

I have the correct SchemaDataTable, provided this and I can have access to the DeltaChange with the updated fields.

Thanks!