LlblGenPro and Not Null fields

Posts   
 
    
Shorty
User
Posts: 18
Joined: 12-Jan-2007
# Posted on: 19-Jan-2007 13:29:48   

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.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 19-Jan-2007 16:48:14   

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

Shorty
User
Posts: 18
Joined: 12-Jan-2007
# Posted on: 22-Jan-2007 12:04:05   

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.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39896
Joined: 17-Aug-2003
# Posted on: 23-Jan-2007 11:54:27   

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.

Frans Bouma | Lead developer LLBLGen Pro
Shorty
User
Posts: 18
Joined: 12-Jan-2007
# Posted on: 24-Jan-2007 18:39:10   

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

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39896
Joined: 17-Aug-2003
# Posted on: 24-Jan-2007 20:29:48   

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.

Frans Bouma | Lead developer LLBLGen Pro