Setting a "null" value to a optional property sometimes fails (reproducable)

Posts   
 
    
Posts: 256
Joined: 05-Jul-2010
# Posted on: 26-Feb-2013 16:00:30   

Hi

I have a reproducable scenario where I cannot set a value of a field to "null".

You need northwind, included. Startup the app and press the button BUG. Now do as it mentions.

  1. Make sure the field reportsTo inside employee is set to null for employeeid == 1 update [Northwind].[dbo].[Employees] set ReportsTo = null where EmployeeID = 1; use managementstudio or something like that

  2. Click the first dialog away AFTER this is done

  3. Now go and change this value to any other value then NULL\n update [Northwind].[dbo].[Employees] set ReportsTo = 2 where EmployeeID = 1;");

  4. Click the second dialog away after you have execute the statement.

  5. You'll see that from this point on, it became ipossible to set the value of reportsto to null...

thanks for having a look at it.

Posts: 256
Joined: 05-Jul-2010
# Posted on: 26-Feb-2013 16:03:51   

with attachment, but a bit limped because of sizelimit of 1.1K

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 26-Feb-2013 20:53:54   

Forcing write on the field doesn't signal the field as changed. So when you try setting it to null, the frameowrk still sees it as having null already, so it doesn't attempt to really set it.

To solve this, just signal the field as changed after forcing the write.

fldTarget.ForcedCurrentValueWrite(newValue);
fldTarget.IsChanged = true;
Posts: 256
Joined: 05-Jul-2010
# Posted on: 27-Feb-2013 09:57:45   

Walaa wrote:

Forcing write on the field doesn't signal the field as changed. So when you try setting it to null, the frameowrk still sees it as having null already, so it doesn't attempt to really set it.

To solve this, just signal the field as changed after forcing the write.

fldTarget.ForcedCurrentValueWrite(newValue);
fldTarget.IsChanged = true;

Hi Walaa

The thing is that I don't want to mark the field "as changed". What actually happens in reality is that the object is changed in the database. Through a backgroundloader, the object comes to my "ui" thread. I need to merge this latest data with the existing in memory object. That is why I would like to overwrite the existing fields without flagging the object or field as changed. I don't want it to "save" again because all fields on all clients have updated.

The problem, I used reflector, is that the internal DBFieldValue is still set to null. Which makes sense, since I did a dirty hack.

How could I overwrite all the values of a field by a new value and mark the field as "bright, shiny and freshly downloaded" from the database. It can even throw away any existing new values.

thanks

A

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 27-Feb-2013 18:35:20   

Why do you copy fields instead of just refreshing/refetching/replacing the in-memory entities.

Posts: 256
Joined: 05-Jul-2010
# Posted on: 27-Feb-2013 19:40:54   

Walaa wrote:

Why do you copy fields instead of just refreshing/refetching/replacing the in-memory entities.

Refresh/refetch is not an option. Now I have the advantage that all objects are fetched asynchronous. I also don't know what objects to fetch in advance. I fetch async all objects from a table with a timestamp higher then the last "fetch timestamp". After I've fetched these in thread X, I need to synchronize this with the UI thread.

Replacing doesn't work because of binding to the original object. It might be currently edited and that would mean I have two instances of the same object. I know that a context prevents this, but then I cannot go multithreaded. Replacing an object would also lose all data that is not stored in llblgenpro fields. We inherit these objects to expand them with "other" non data properties.

I have to admit that I don't use llblgenpro out of the book, because I have some very specific needs from my app. Limited amount of data that refreshes often and of which people expect live updates.

threadpool gets me all objects where table.Version > @lastversion. Synchronize objects with UI thread Merge objects inside existing collections and screens. if object existed before, merge object in old instance, check sorting on all collections if new object, insert inside collections

kind regards

a

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 28-Feb-2013 08:16:41   

I don't follow all the detail of your architecture, but, if I think you want to manipulate the DBValue. You also didn't mention your LLBLGen version. Assuming that you are using v3.5, you can use some of these methods, maybe they can be useful in your case:

theEntity.Fields[(int)CustomerFields.Country].ForcedCurrentValueWrite(true / false);
theEntity.Fields[(int)CustomerFields.Country].ForcedChangedWrite(true / false);
theEntity.Fields[(int)CustomerFields.Country].ForcedIsNullWrite(true/false);
theEntity.Fields[(int)CustomerFields.Country].SetDbValue(null);
David Elizondo | LLBLGen Support Team
Posts: 256
Joined: 05-Jul-2010
# Posted on: 28-Feb-2013 09:35:26   

daelmo wrote:

I don't follow all the detail of your architecture, but, if I think you want to manipulate the DBValue. You also didn't mention your LLBLGen version. Assuming that you are using v3.5, you can use some of these methods, maybe they can be useful in your case:

theEntity.Fields[(int)CustomerFields.Country].ForcedCurrentValueWrite(true / false);
theEntity.Fields[(int)CustomerFields.Country].ForcedChangedWrite(true / false);
theEntity.Fields[(int)CustomerFields.Country].ForcedIsNullWrite(true/false);
theEntity.Fields[(int)CustomerFields.Country].SetDbValue(null);

The fldTarget.SetDbValue(newValue); fldTarget.ForcedCurrentValueWrite(newValue);

Combination solves my issue.

Thanks

a