- Home
- LLBLGen Pro
- Bugs & Issues
LlblGenPro and Not Null fields
Joined: 12-Jan-2007
I beleive there is an issue will LlblGen and the way it handles not null string fields and heres why.
CREATE TABLE test(id as PK field ,mand VARCHAR2(3) NOT NULL ,notmand VARCHAR(3))
If I create on entity based on this table then I perform an insert as follows
Dim ent as New testentity ent.id = 50000 ent.mand = nothing (This is a mandatory field and cannot be null...should cause object error) ent.notmand = nothing Using adap As New DataAccessAdapter adap.saveentity(ent) End Using
Firstly llblgen attempts to persist the object when its INVALID wasting database resource. However at least the db results in an exception.
A far worse situation is using the entity to perform an update e.g. record in table (1,"POPULATED",null)
Dim ent as new testentity ent.id = 1 Using adap As New dataacessadapter ''' fetch entity from database ''' ent.Id = 1 ''' ent.mand = "POPULATED" ''' ent.notmand = Nothing adap.fetchentity(ent) '' change fields ent.mand = nothing (This is a mandatory field and cannot be null...should cause object error) ent.notmand = "TEST" ''' persist to db adap.saveentity(ent) End Using
Again llblgen attempts to persist the object when its INVALID. Here no error is raised and an update IS performed on the db. If the object is refetched it looks like this ent.Id= 1 ent.mand="POPULATED" ent.notmand = "TEST"
This is WRONG..............as it isnt what was requested.
If I put my .net transaction in ddl speak it should produce the following
UPDATE test SET mand = null,notmand="TEST" WHERE id=1. This will always result in database error.
In reality the following happens in llblgenpro for not null fields. If the field fails not null validation in ValidateValue in entitybase2, the entire column is stripped out of any subsequent transaction to the db. The ddl produced now looks like UPDATE test SET notmand="TEST" where id = 1, this update can be performed and its why my entity is refetched as above.
First rule of databases is if you cannot do what I ask then dont do it all, leaving the data as it is. Here in llblgen my request is reformatted "behind the scenes" then sent to the database. This practice IMHO is more than a little dubious.
Is it a bug or in microsoft terminology "by design". ValidateValue is causing me some really unaticipated side effects when I test my app.
LLBLGen Pro generates the SQL Query (Insert or Delete) to only contain those fields who have a value (i.e. the entityFields where there default values have changed)
That's why in your 2 cases the mand field was not generated in the SQL query, since nothing / null is the default value for the string .NET dataType.
LLBLGen Pro detected that the mand field value was not changed, therefore it did not generate it in the SQL query.
That's why you have recieved an exception from the databse in the INSERT case, but not in the UPDATE case.
To make sure of this, you might set ent.mand.IsChanged = true, before you save to the database.
Now the question is: How to avoid going to the database if the Entity is INVALID?
The answer is, LLBLGen Pro doesn't define the validity of the entity, but it leaves this issue for you, through validation code. Please refer to the LLBLGen Pro manual: Using the generated code -> Validation per field or per entity
Joined: 12-Jan-2007
Thanks Walaa
The problem is I did change the mandatory field from something to nothing. I spent an age debugging my own code when I tested it using and asp.net 2 formview without asp validators. Having cleared a mandatory field and made changes to a non mandatory field then clicked save. The results after the refetch appeared to show an incomplete transaction namely the mandatory field unchanged and the non mandatory field altered. If this confused me I cant imagine what a user would feel.
Actually what happened was my request was altered by llblgenpro to update only the non mandatory field and leave the mandatory field untouched.
This may be OK in the situation where I know that if I have a mandatory field I can place an requiredfieldvalidator on the form, yet if I expose the object as a web service the how can I audit any transaction if the request is altered internally.
Surely if I set a number of properties at the same time and one is blatantly invalid then raising an exception is the way to go.
e.g. If a string is to long for a database field an ArgumentOutRange exception is thown. Meaning the task requested cannot be performed.
Yet if I set a mandatory field to nothing no error is raised. From validatevalue in entitybase2 only a boolean flag is set (e.g. if(value==null) { validateResult = fieldToValidate.IsNullable; } No on onvalidatefield is performed so there no way of letting a user know.
Simply put, if I cant perform the action requested no action should be performed.
First of all: it's impossible to answer these kind of questions without information like: - DB type, version ? - llblgen pro version ? - runtime lib BUILD nr ?
This is important as NULL and "" is the same for string fields in Oracle for example.
Shorty wrote:
I beleive there is an issue will LlblGen and the way it handles not null string fields and heres why.
CREATE TABLE test(id as PK field ,mand VARCHAR2(3) NOT NULL ,notmand VARCHAR(3))
If I create on entity based on this table then I perform an insert as follows
Dim ent as New testentity ent.id = 50000 ent.mand = nothing (This is a mandatory field and cannot be null...should cause object error) ent.notmand = nothing Using adap As New DataAccessAdapter adap.saveentity(ent) End Using
Firstly llblgen attempts to persist the object when its INVALID wasting database resource. However at least the db results in an exception.
The ent.mand=nothing statement won't result in the field being set to a value. You'll see that ent.Fields["mand"].IsChanged is still false.
This has to be caught by a validator you set on the entity in the beforesave validation. The thing is that omitting the line ent.mand=nothing will result in the same thing: a NULL being inserted. You can catch these mistakes in a validator, by simply checking if mandatory fields have a value set (i.e. the field objects are marked changed) and if not, throw an exception. There's simply no other way to do this, as the end result for a field set to NULL and a field which didn't receive a value is for an INSERT statement the same: NULL will be inserted into the field.
A far worse situation is using the entity to perform an update e.g. record in table (1,"POPULATED",null)
Dim ent as new testentity ent.id = 1 Using adap As New dataacessadapter ''' fetch entity from database ''' ent.Id = 1 ''' ent.mand = "POPULATED" ''' ent.notmand = Nothing adap.fetchentity(ent) '' change fields ent.mand = nothing (This is a mandatory field and cannot be null...should cause object error) ent.notmand = "TEST" ''' persist to db adap.saveentity(ent) End Using
Again llblgen attempts to persist the object when its INVALID. Here no error is raised and an update IS performed on the db.
You're sure there's an UPDATE query generated? As there are no fields dirty: mand will still contain POPULATED, as the field can't be set to null, so the internal validation routine will say "no, the field can't be set", so nothing is set.
If the object is refetched it looks like this ent.Id= 1 ent.mand="POPULATED" ent.notmand = "TEST"
This is WRONG..............as it isnt what was requested.
No, this is correct, as mand wasn't set to a value, because nothing was an illegal value so the field wasn't set.
Is it a bug or in microsoft terminology "by design". ValidateValue is causing me some really unaticipated side effects when I test my app.
Why is it unexpected? It exactly does what it should: it returns false for 'nothing' as nothing is an invalid value for the field, so the field isn't set to a value.
Joined: 12-Jan-2007
Otis
Cheers for the reply
Useful info Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production LLblGenPro v2.0 (6/12/2006) ORM Support Libraries 2.0.0.61205
SD_ID NUMBER(10) NOT NULL SD_ADDRESS VARCHAR2(200) Databefore using LLblGenPro PK
SD_ID SD_ADDRESS
10100 TestBefore
-- Run page dont catch any exceptions (test for PK violations in entity)
/// Simple Page Load Test... Want to set PK to null and change address Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim ent As New SppsSiteDetailsEntity ent.SdId = 10100 Using adap As New DataAccessAdapter adap.FetchEntity(ent) ent.SdId = Nothing -- PK set to Null ent.SdAddress = "TestAfter" adap.SaveEntity(ent) End Using End Sub
DataAfter using LLlblGenPro SD_ID SD_ADDRESS
10100 TestAfter
As you can see no exception is thrown when setting PK invalid along with an update being performed on the SD_ADDRESS field in my database.
If I tried this as a ddl update statement against the db it would be
UPDATE <table> SET SD_ID=null,SD_ADDRESS="TestAfter" WHERE SD_ID = 10100.
As you can see the information Ive requested to be altered has not conformed to my update statement as an Oracle error would occur. LlblGen has modified my request. I would have expected an exception to occur when ent.SdId= Nothing which I could catch and process before I called adap.SaveEntity(ent).
Is this the expected behaviour??
Cheers
Shorty
Yes, as the PK isn't set by the action you did. Please read my reply about field changes and why invalid values are rejected before the field is set, and thus that the field isn't set.