0

I'm having a problem when I insert a Guid value in an Oracle database (raw(16) field). I'm using the Devart library in my C# application to record records. The error occurs randomly because I use Guid.NewGuid() to generate the values that will be recorded in the table.

I was able to simulate through a test project a Guid value that causes the problem. I would like to know if I can create a validation method to assess whether a Guid value generated by Guid.NewGuid will represent a valid value when recorded in the Oracle database.

Below is the test project used to simulate the problem and the evidence of the invalid value recorded in the database:

Test code:

[TestMethod]
public void RegraNegocio_GerarGuids2()
{
    int id;
    CanalVenda canalVenda = null;
    CanalVenda canalVenda2 = null;

    try
    {
    canalVenda = CanalVenda.New();
    canalVenda.RowGuid = Guid.Parse("d8a5feff-51da-4101-9889-77bec5339077");
    canalVenda.Nome = $@"Teste Guid {canalVenda.RowGuid.ToString()}";
    id = canalVenda.Save().Id;
    canalVenda2 = CanalVenda.Get(id);
    }
    catch (Exception e)
    {
    throw new Exception($@"Guid: {canalVenda.RowGuid} - Erro: {e.Message}");
    }
}

The value recorded in the database: screenshot

Note: Before being written to the database, the value of the Guid variable is converted to a byte array to be compatible with the raw(16) field.

Guid guidValue = (Guid)value;
value = guidValue.ToByteArray();

In C#, we tried to use the length property to find out if the invalid Guid size was different from a valid Guid, but we were unsuccessful.

joeljpa
  • 317
  • 2
  • 13
  • Please remove the non-english part. Its hard to even find where the relevant part starts. Don't make it hard to help you. – Ralf Jun 21 '23 at 13:53
  • It reads weird but looking at the help for [SYS_GUID](https://docs.oracle.com/cd/B13789_01/server.101/b10759/functions153.htm) they used raw(32) not raw(16) as datatype here. Might be just broken docu but still. – Ralf Jun 21 '23 at 14:44

1 Answers1

0

A GUID is, per definition, 16 bytes long. No longer or shorter. This is unlikely a source of error.

If there is any issue it is most likely in the interface layer to the database. Are you sure the object conversion part works as you expect it to? A common way to serialize an array is to add the length as a prefix, are you sure nothing like this is done by your ORM?

I'm kind of chocked that Oracle does not seem to have a native GUID/UUID data type, since that would likely make things easier.

Note that the byte order may not match what you expect: 1 2. But as long as you use the .net methods to convert between byte array and GUID it should not matter. new Guid(myGuid.ToByteArray()) should always produce the original value.

I would remove the GUIDs from the equation and just add some 16-byte arrays to the database and verify that the same values are returned. I would test with all zeroes, all byte.MaxValue, and random values.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • 1
    I found an article that suggests using the OracleBinary structure to convert the byte array to Oracle Binary before writing to the field. Below is the conversion suggestion made in the article: ```Guid guid = Guid.Parse(guidString); OracleBinary oracleBinary = new OracleBinary(guid.ToByteArray()); return oracleBinary.Value;``` – Leonardo Souza Jun 21 '23 at 17:32
  • 1
    OracleBinary documentation from the devart library: [link](https://docs.devart.com/dotconnect/oracle/Devart.Data.Oracle~Devart.Data.Oracle.OracleBinary.html) – Leonardo Souza Jun 21 '23 at 17:37