I was getting IdNotSetEception ("Id not set on entity of class TXXX") firing on tables and couldn't immediately see any difference in my code. Some table it worked for, others it didn't.
I then realised that the tables that had this issue had a row where the ID column was zero. As zero is a valid ID value, this is surely a bug? Looks like there is a check somewhere that confuses zero and null.
That is not a bug, but a desired behavior. Zero is considered a null id. When you have an object with a property Id: Integer, it's the way Aurelius tell that such class is transient and needs to be inserted and get a new id (or that the class doesn't have an id yet and generate an error if it's not auto generated).
There is an undocumented attribute named IdUnsvedValue that you can use to work around that. That attributes allow you to change the default "null id" value, which is 0 by default:
[Entity, Automapping]
[IdUnsavedValue(-1)]
TUnsavedValue = class
This way Aurelius will understand that when ID is -1 then that's when the class doesn't have an id. You must be sure to initialize your property with that value when a class is created otherwise Aurelius will always try to update the data (and not insert).
Ooohh. That's a bit nasty, if you don't mind me saying so. :-) Databases have always been using null to signify this exact situation. Maybe, could we have a new class (the opposite of Nullable<>) which would allow you to specify the need for a new ID? Maybe PrimaryKey<> or some such? That would allow you to specify a field ID: PrimaryKey<integer> which would be nullable to indicate 'no value'?
Well, having to create things like PrimaryKey<> to pollute pure Delphi classes and let the developer "remember" all the time that such a type is there only to persist the value in the database is nastier for me... :-)
And primary keys are not nullable, actually, why would mapping represent something that has a null value if it's not desired in both OOP programming and database? Having a zero value as an id is in theory a source of a lot of problems, even Delphi basic Field.AsInteger access treat null values as zeros - you would have to do lots of if's to determine what is the current situation.