- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
default values
Joined: 18-Jul-2006
When I create an entity, I'd like its fields to be initialized to the column default set up in SQL Server. Is there any straightforward way to do this? I'm running version 1.0.2005.1.
Dim x As New WhateverEntity
' The column default for MaximumCharge is 5000 in SQL Server, yet this displays 0:
MessageBox.Show(x.MaximumCharge.ToString())
x.Save()
' Now the value is 5000. It's only set when the entity is fetched back?
' Any way to "fix" this?
MessageBox.Show(x.MaximumCharge.ToString())
Joined: 18-Jul-2006
The app I'm creating is not the only one using this database, so I do not want to take the default values out of the database and make them the sole responsibility of my app.
Nor do I want to hand-code this knowledge in two different places: the database and my app.
I want the database to be the source of knowledge for what the default values are, and for LLBLGen to honor those defaults when it creates an entity. Is there anything illogical about that? If there is, could you explain? If there isn't, do you have an answer to my original question?
Joined: 18-Jul-2006
Look at it as a contract of sorts: The entity is NOT in a valid state when created unless it has particular values. "New" is what creates an entity, not "Save". Save just persists the entity to the database.
The source of knowledge for the default states is in the database, but that does not mean that it's illogical for client apps to honor those defaults when they create objects. In fact, I believe they should.
Can anyone answer my actual question of how to accomplish this in LLBLGen? I'm sure it's possible. LLBLGen has access to all kinds of metadata when it generates the code; surely it has access to the default values.
BrianH wrote:
Look at it as a contract of sorts: The entity is NOT in a valid state when created unless it has particular values. "New" is what creates an entity, not "Save". Save just persists the entity to the database.
No, an entity is not in a valid state for READING if it hasn't been saved. This is because an entity in MEMORY is a mirror/copy of the real entity in the persistent storage.
the only real entity is in the db. All other instances are copies.
The source of knowledge for the default states is in the database, but that does not mean that it's illogical for client apps to honor those defaults when they create objects. In fact, I believe they should.
Can anyone answer my actual question of how to accomplish this in LLBLGen? I'm sure it's possible. LLBLGen has access to all kinds of metadata when it generates the code; surely it has access to the default values.
The default values aren't stored in the meta-data as they're defined in the tables in the database. Storing them in the meta-data would mean a maintenance issue when defaults change in the db and not in the code, which might be overlooked. if you want to initialize your entity with default values in memory, you should do that in code. If you want to use the default values set by the DB, leave the fields as-is and save the entity, with refetch (adapter) (selfservicing will refetch for you).
Also, if an entity is saved in oracle and sqlserver and uses a typeconverter to convert a value to a type compatible with oracle (e.g. bit -> number(1,0)), the meta-data for the default couldn't be stored in the entity itself, but in the dbspecific meta-data, something you don't want to use for entity usage when no persistence logic is necessary.
Joined: 18-Jul-2006
Thanks for your response and for your fine product. Please bear with me a bit, while I try to understand.
When you say:
an entity is not in a valid state for READING if it hasn't been saved.
you mean, as far as LLBLGen's current implementation it's not valid, right? In other words, you're not making a philosophical point, but a point about LLBLGen's current implementation. But what about the philosophical point? When one sets a default value in SQL Server, isn't one saying something fundamental about the entity being modeled? And regardless of how that entity (or copies of it, if you prefer) are created, shouldn't they honor that constraint?
The default values aren't stored in the meta-data as they're defined in the tables in the database. Storing them in the meta-data would mean a maintenance issue when defaults change in the db and not in the code, which might be overlooked.
I'm not sure I understand, or perhaps I used "metadata" in the wrong way. What I'm asking, without using that word, is this: When the LLBLGen designer is generating the code, is it not possible for it to determine what the default values of the entities are and emit code to set them? And if the answer is yes, but the defaults may later be changed and then the code would be out of sync with the database, doesn't that happen anyway if someone changes the type of the data?
If you want to use the default values set by the DB, leave the fields as-is and save the entity, with refetch (adapter) (selfservicing will refetch for you).
I thought of this, but what if the user cancels the operation? Then I have to delete the entity from the database, and in the interim an entity has been in the database that the user never intended to be there.
These are the constraints I'm operating under: 1. The user knows, roughly, what the default values should be for the entity they're working with. When he hits the "New" button, he expects to get a form where the controls already have the default values which he can alter if he wishes, and then press either Save or Cancel. It seems unnecessarily confusing to present him with a form with zeros and blanks instead which are then automagically changed AFTER he hits save. 2. The user uses a variety of apps to manipulate these entities. If their default values need to be changed, we'd like to do that in just one place, the database. 3. I could do a save in the background (not user-directed) to get the default values, then copy the default values and delete the entity, all inside a transaction so that a this temporary entity is never there from the perspective of other users of the database, then use the copied defaults to populate a new entity which isn't saved until the user directs, but that seems awfully convoluted to do something so simple.
I just found this thread: http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=6793&HighLight=1 which seems to have you very straightforwardly saying you can modify a template to achieve the behavior I want. But it appears to apply just to version 2. Is that correct? Is there a simple way to do it in version 1?
Joined: 10-Mar-2006
These are the constraints I'm operating under: 1. The user knows, roughly, what the default values should be for the entity they're working with. When he hits the "New" button, he expects to get a form where the controls already have the default values which he can alter if he wishes, and then press either Save or Cancel. It seems unnecessarily confusing to present him with a form with zeros and blanks instead which are then automagically changed AFTER he hits save. 2. The user uses a variety of apps to manipulate these entities. If their default values need to be changed, we'd like to do that in just one place, the database. 3. I could do a save in the background (not user-directed) to get the default values, then copy the default values and delete the entity, all inside a transaction so that a this temporary entity is never there from the perspective of other users of the database, then use the copied defaults to populate a new entity which isn't saved until the user directs, but that seems awfully convoluted to do something so simple.
Defaults in a database - for me - are things I want the fields to default to if they are not provided when a new record is inserted.
You are actually trying to set defaults in the datbase that are default UI field settings. Then you are wanting to do "new MyEntity()", read the values out of the entity and put them in your UI - right?
That is interesting - I can see that use. I could see this being a feature in the core product - where you could [optionally] have default values applied to then entities when they are 'newed up'. I like it - Otis, what do you think?
I just found this thread: http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=6793&HighLight=1 which seems to have you very straightforwardly saying you can modify a template to achieve the behavior I want. But it appears to apply just to version 2. Is that correct? Is there a simple way to do it in version 1?
I think this can be done in version 2005.1, unless the new 'DefaultValue' property is new to the metadata for v2. Also, consider going up to version 2 - conversion not bad and seems to work nicely.
BrianH wrote:
Thanks for your response and for your fine product. Please bear with me a bit, while I try to understand.
When you say:
an entity is not in a valid state for READING if it hasn't been saved.
you mean, as far as LLBLGen's current implementation it's not valid, right? In other words, you're not making a philosophical point, but a point about LLBLGen's current implementation.
No it is a philosophical point .
But what about the philosophical point? When one sets a default value in SQL Server, isn't one saying something fundamental about the entity being modeled? And regardless of how that entity (or copies of it, if you prefer) are created, shouldn't they honor that constraint?
A default value constraint in an RDBMS is as Wayne explained: when no value is provided the value of the constraint has to be the value for the field.
Entity definition: abstract definition of what the entity consist of in the case of attributes: e.g. 'Customer' consists of 'CustomerId, CompanyName etc. ' and is uniquely identified by 'CustomerId'. that's not physical, that's an abstract definition. Entity instance: data which represents an instance of an entity definition. Table / view / resultset definition: physical definition of an entity definition (which is abstract) Entity class: physical definition in code of the entity definition (e.g. similar to table/view/resultset definition) Entity object: instance of entity class, which acts as a container for an entity instance (== data!) Filled entity object: as Entity object, but now it contains an entity instance in memory, or better: it contains a mirror/copy of an entity instance, IF the entity instance in the entity object is actually available in the persistent storage. If not, it's a new entity instance not yet saved and not yet valid. It's not yet valid because if the save fails due to for example concurrency issues or constraint issues, the entity has to be rejected.
For Jimmy Nilsson's book Applying Domain driven design and patterns, I've written an essay about this, which is in the appendix of that book. I'll post it on my blog shortly, which explains this in greater detail.
The core point is that an entity object is nothing more than a container. It's not an entity instance. So if you simply create an entity class instance (== entity object) you have a container and nothing else. If you load an entity instance into it (read it from the persistent storage or copy it over from another entity object), it contains an entity, but it will never become an entity, as it's a container, not the entity itself.
This thus also means that if you create an entity class instance and you initialize some fields with default values, it has no real value: by definition you shouldn't read these fields and base actions on the values. This is because the entity might be invalid due to rules setup in the real entity habitat: the persistent storage. For example there's already an entity with that PK value, or an entity which has the same values for the UC field in the entity definition, or the value for a given FK field violates an FK constraint.
You might want to initialize fields with a given value so the user or a process doesn't have to set these themselves already, but that's actually doing the same thing as a default constraint in the rdbms: you provide a value for a field if no value is given.
The default values aren't stored in the meta-data as they're defined in the tables in the database. Storing them in the meta-data would mean a maintenance issue when defaults change in the db and not in the code, which might be overlooked.
I'm not sure I understand, or perhaps I used "metadata" in the wrong way. What I'm asking, without using that word, is this: When the LLBLGen designer is generating the code, is it not possible for it to determine what the default values of the entities are and emit code to set them? And if the answer is yes, but the defaults may later be changed and then the code would be out of sync with the database, doesn't that happen anyway if someone changes the type of the data?
Default values for fields are available in the meta-data of the project, that is: IF the RDBMS reports them as such. Often these defaults are functions, which have to be run at insert time. So they're not of that much value in code. For example, the default value for a 'LastModifiedOn' field could be GETDATE() in sqlserver. That's of no value in code, unless you convert it to DateTime.Now.
But is that value really true? What if you save it 10 minutes after creation? Then LastModifiedOn is not containing a valid value.
What people do is to create an include template when they're on v1.0.2005.1 for the entities and in there set fields to a value if the fields object's state property is New. On v2.0, they can override OnInitialized in an entity, for example by a partial class, and set the initial field values there.
If you want to use the default values set by the DB, leave the fields as-is and save the entity, with refetch (adapter) (selfservicing will refetch for you).
I thought of this, but what if the user cancels the operation? Then I have to delete the entity from the database, and in the interim an entity has been in the database that the user never intended to be there.
No, as you should never base your actions on a NEW entity's values in-memory, unless you realize you base your actions on data which might be invalid after you're done. This is because it can be another thread inserted an entity during the process of your thread which makes the entity you're holding invalid. It's not a big deal though. It's a change of thinking how to work with entities, see my explanation above. If you realize the entities you work with are perhaps invalid because they're NEW, you thus have to work with the consequence that when the persist action fails, you thus have to rollback your complete process and start over.
Joined: 18-Jul-2006
The core point is that an entity object is nothing more than a container. It's not an entity instance. So if you simply create an entity class instance (== entity object) you have a container and nothing else. If you load an entity instance into it (read it from the persistent storage or copy it over from another entity object), it contains an entity, but it will never become an entity, as it's a container, not the entity itself.
I think this goes without saying. An entity is a concept, a Platonic construct. The bits in the database itself aren't entities either.
This thus also means that if you create an entity class instance and you initialize some fields with default values, it has no real value: by definition you shouldn't read these fields and base actions on the values.
I agree that you can't assume that what you have in memory constitutes a valid entity-as-modelled-in-the-database until you save it and the database successfully enforces all the constraints that only it can enforce. But that doesn't mean there isn't value to showing the user the default values (where they are constants, not functions) in the GUI when he's filling out the form to create a new entity.
You might want to initialize fields with a given value so the user or a process doesn't have to set these themselves already, but that's actually doing the same thing as a default constraint in the rdbms: you provide a value for a field if no value is given.
Yes, but the reason the default is there in the database, in many cases, is these are values that "make sense" for a new entity. I.e., it's not just to satisfy a practical concern of what to put in the field if no value is given. It's making an assertion about the typical initial state of an attribute. Or am I mistaken here? If I'm right, then I'd like to honor that assertion about the typical initial attribute (if it's a constant, not a function) on the front-end by showing this value in the GUI when the user pulls up a form to create a new entity. And I'd like to do that without having to hand-code these specific values in my code.
Default values for fields are available in the meta-data of the project, that is: IF the RDBMS reports them as such. Often these defaults are functions, which have to be run at insert time. So they're not of that much value in code. For example, the default value for a 'LastModifiedOn' field could be GETDATE() in sqlserver. That's of no value in code, unless you convert it to DateTime.Now. But is that value really true? What if you save it 10 minutes after creation? Then LastModifiedOn is not containing a valid value.
What you write here is very persuasive. After all, if we can't honor all the defaults in the front end, maybe we shouldn't honor any of them. Still, there seems to be a difference to me between defaults which are constants and those which are functions, at least from the point of view of the user. The user knows that a default value based on a function is going to vary, so he won't expect to see a prepopulated in the GUI, but for a constant default, he's more likely to expect that. Once you accept this expectation as valid, then the question becomes, how do you honor it without having to hand-code the default value in the front-end?
What people do is to create an include template when they're on v1.0.2005.1 for the entities and in there set fields to a value if the fields object's state property is New. On v2.0, they can override OnInitialized in an entity, for example by a partial class, and set the initial field values there.
I'm still unsure if it's possible to have the fields set to the database's constant default values without having to hand-code those values. The other thread, and the previous poster, mention the 'DefaultValue' metadata property, but I can't find where it's documented (a search of both help files turned up nothing). Where do I look for documentation on it? I feel guilty chewing up your time with this thread, so that's the core question for me.
Joined: 10-Mar-2006
I'm still unsure if it's possible to have the fields set to the database's constant default values without having to hand-code those values. The other thread, and the previous poster, mention the 'DefaultValue' metadata property, but I can't find where it's documented (a search of both help files turned up nothing). Where do I look for documentation on it? I feel guilty chewing up your time with this thread, so that's the core question for me.
The metadata he is referring to is what the LLBLGen designer makes available to the templates when it generates code.
So, you can write your own template that gets put into every entity object. When your template is called you can iterate through all the fields defined on the entity and write out code that uses (DBTableField)(currentIteratedField.MappedField).DefaultValue. This would be for an lpt template. It would be even easier for the other template type - however they are less flexible.
I found this in the LLBLGenProSDKReferenceManual help file.