Binary Datatype removed from 2009

Microsoft removed the support for the binary data type from the 2009 service tier.

This makes working with streams received from Message Queues and TCP/sockets impossible.
The reason for this is that a pure “COPYSTREAM” does not work as Navision reads forever no matter if the stream is over or not.

The next problem that we have with this has to do with our data replication mechanism.

We concat all records including their blobs and additional data into a single stream and also have to read from this stream to rebuild the records on the other side.
The binary datatype is critical for this behavior, otherwise writing several blobs into one stream would not work.

The only other option which would solve this problem would be an additional paramter for the number of bytes to be read for the COPYSTREAM function.

Until now we have used our own “COPYSTREAMWITHSIZE” function (all variables named DataX are of the type binary with the specified size:

COPYSTREAMWITHSIZE(VAR OutStrm : OutStream;VAR InStrm : InStream;StreamLen : Integer) BytesCopied : Integer
WHILE (StreamLen >= 2000) AND (NOT InStrm.EOS) DO BEGIN
```BytesRead := InStrm.READ(Data2000); StreamLen -= BytesRead; BytesCopied += OutStrm.WRITE(Data2000,BytesRead); END; WHILE (StreamLen >= 500) AND (NOT InStrm.EOS) DO BEGIN BytesRead := InStrm.READ(Data500); StreamLen -= BytesRead; BytesCopied += OutStrm.WRITE(Data500,BytesRead); END; WHILE (StreamLen >= 200) AND (NOT InStrm.EOS) DO BEGIN BytesRead := InStrm.READ(Data200); StreamLen -= BytesRead; BytesCopied += OutStrm.WRITE(Data200,BytesRead); END; WHILE (StreamLen >= 50) AND (NOT InStrm.EOS) DO BEGIN BytesRead := InStrm.READ(Data50); StreamLen -= BytesRead; BytesCopied += OutStrm.WRITE(Data50,BytesRead); END; WHILE (StreamLen >= 20) AND (NOT InStrm.EOS) DO BEGIN BytesRead := InStrm.READ(Data20); StreamLen -= BytesRead; BytesCopied += OutStrm.WRITE(Data20,BytesRead); END; WHILE (StreamLen >= 5) AND (NOT InStrm.EOS) DO BEGIN BytesRead := InStrm.READ(Data5); StreamLen -= BytesRead; BytesCopied += OutStrm.WRITE(Data5,BytesRead); END; WHILE (StreamLen >= 1) AND (NOT InStrm.EOS) DO BEGIN BytesRead := InStrm.READ(Data1); StreamLen -= BytesRead; BytesCopied += OutStrm.WRITE(Data1,BytesRead); END;`

Anybody out there with a good suggestion?

Have you tried to read/write a char instead of binary? May be the performance drawback is not too bad…

char is eight times worse than BigInt which would be the biggest “simple” datatype which can be used instead of binary.

Anyway the factor between reading 8 byte chunks of a 80k file is 10000 transactions in a loop (read + write) or 5 transactions with 2000 bytes each.

Anyway, the RTC sucks all together as ComCom is not working anymore as well as events (no matter if client or server side).

Well, I tested the time behavior with a simple file copy function and, indead, if one uses reading and writing one char a time, the copying lasts about 1000 times longer as in the case of a Binary2000.

But, nevertheless, I have a suggestion of improvement four your COPYSTREAMWITHSIZE function (though you may not need it anymore…):

COPYSTREAMWITHSIZE(VAR OutStrm : OutStream;VAR InStrm : InStream;StreamLen : Integer) BytesCopied : Integer
REPEAT
BytesRead := InStrm.READ(Data2000);
IF BytesRead > 0 THEN BEGIN
BytesWritten := OutStrm.WRITE(Data2000,BytesRead);
// eventually test if BytesWritten = BytesRead...
BytesCopied += BytesWritten;
END
UNTIL InStrm.EOS;

StreamLen is not needed, if you want to read InStrm to EOS (otherwise the code can easily be adapted to read exactly StreamLen bytes). The clue is to use the return value of OutStrm.WRITE, which suppresses the error, which would occur otherwise if BytesRead is less than 2000, since OutStrm.WRITE(Data2000,BytesRead) throws an (unexpected) error, if BytesRead is less than 2000 and the return value of the WRITE function is not used.

Thanks for the try, but your assumptions are wrong.

1st. Instrm.EOS does NOT always really recognize the end of the stream (just try to send and receive a file through MSMQ, I have a test object for you if you do not believe it)

2nd. We need to read only a certain part of a stream (lets say from byte 125 to bytes 2378) and not the complete one.

3rd. Data2000 (binary) is not supported in RTC anymore.

sorry, I edited my post during you were writing yours…

ok, here is the code, if you want to read a certain number of bytes from InStrm and copy it to OutStrm. I tested this code to copy a file partially (first 12345 bytes) to annother file (with NAV 5.0 SP1):

COPYSTREAMWITHSIZE(VAR OutStrm : OutStream;VAR InStrm : InStream;StreamLen : Integer) BytesCopied : Integer
REPEAT
IF StreamLen >= 2000 THEN
BytesRead := InStrm.READ(Data2000)
ELSE
BytesRead := InStrm.READ(Data2000,StreamLen);
StreamLen -= BytesRead;
IF BytesRead > 0 THEN BEGIN
BytesWritten := OutStrm.WRITE(Data2000,BytesRead);
// eventually test if BytesWritten = BytesRead...
BytesCopied += BytesWritten;
END
UNTIL InStrm.EOS OR (StreamLen = 0);

If I replace the two lines
BytesWritten := OutStrm.WRITE(Data2000,BytesRead);
BytesCopied += BytesWritten;
with the simpler line
BytesCopied += OutStrm.WRITE(Data2000,BytesRead);
I receive the error message "The requested size in the stream does not correspond to the variable size", which in my opinion is some kind of bug.

I tried my code in NAV 2009, too, but there seem to be some changes, since I cannot suppress the above error message as in 5.0 (but your original code should work in NAV2009, since it always writes the exact variable size…)

The online help says:

The BINARY data type, used in previous versions of Microsoft Dynamics NAV to store fixed lengths of binary data in a record, is removed from Microsoft Dynamics NAV 2009. If you previously used the BINARY data type, consider using the BLOB Data Type instead.

but I can use Binaries as variables and even as record fields further on without any compilation errors in NAV 2009…
(by the way, it is perhaps possible to use BLOB.CREATEINSTREAM and BLOB.CREATEOUTSTREAM, to copy from one stream to another…)

I don’t have a problem with the function we are currently using (as shown in my original post). That one works just perfectly for a couple of years.

The problem is that the Binary Datatype is not available anymore (in the RTC).

Yes, you will receive an error, if you use variables or fields of type binary in objects and run them from the RTC. In this respect, the online help is somewhat misleading…

Thanks, folks, for your support on this issue.

COPYSTREAM command now supports the third optional parameter “BytesToRead” !!!

Microsoft implemented this change into NAV 2009 SP1.