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.
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.