When using Linq-to-SQL, adding a column to an existing table, and setting a default value on that new column, it seems that Linq to SQL ignores the default value.
Has anyone else experienced this behaviour? Is there a way to fix it, so that Linq-to-SQL or SQL Server automatically sets the default value?
The column I added was of type Bit, with a default value set to 1.
I have now definitively fixed this by using an example from this blog.
partial void OnCreated() {
if (this.DateTimeCreated == null) {
this.DateTimeCreated = DateTime.Now;
}
}
I needed to pass this into a partial datacontext class, as the default one is automatically overwritten every time you change something in the dbml.
Set Auto Generated property to True.
Go into the designer and select "Auto-Sync" value of "OnInsert". This will sync the value when the record is inserted into the database.
I've seen this. What you can do is go into the l2sql designer, view properties for the table column that has a default value. There is a property "Auto generated value", set that to true.
This same value is set to true automatically for the identity column automatically, as in that case SQL Server is generating your row IDs.
I was faced the same problem of boolean data type with default as false and not updating that value
So when i see the database table, i was found there is not primary key was set, therefore when i was set the primary key it was updated find.
so check a table if it has the primary key or not.
If you ever need to change the value in your own code (eg. a type table value with a default) then don't use 'Auto Generated Value' or you'll get this later when you try updating it.
Value of member 'AlternativeQuoteStatus' of an object of type
'OrderDetail' changed. A member that is computed or generated by the
database cannot be changed.
I prefer to set such values when I create the object, with a fallback in OnCreated as described by others here.
Related
I have a column like this:
MYID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
I know that when doing an INSERT it's possible to override the generated value.
However once the row has been created I can't find a way to use an UPDATE to change the value.
Is there a way to do it?
GENERATED ALWAYS means what is says. You cannot override the values. If you want the system to simply ignore the values you provide, you can use OVERRIDING USER VALUES in the INSERT statement. Otherwise you cannot supply values for the GENERATED column. Values for columns defined as GENERATED BY DEFAULT can be overridden by the user.
I have a table in a SQL database with some columns Entdate which is "not nullable" is one of them with type of date.
I have set the default binding of that column with getdate() function. Now in my project I am using Entity Framework (database first) with mvc 4. So I got a property called Entdate in my model (which is generated by Entity Framework, because I am using database first approach). I don't want to pass any value to this (EntDate, because in the database I have used getdate() function as default constraint for the Entdate column) property, I just need to fetch the data from Entdate column from SQL database. How can I do this?
If I remove the set property of the Entdate property in model, it generates an error, I can't pass null value to it because Entdate is not nullable in database. What should I do? Any suggestion will be appreciated. Thanks in advance :)
Set its StoreGeneratedPattern = Computed and its Setter = private as in this example:
Background: we have a Grails 1.3.7 app and are using Liquibase to manage our database migrations.
I am trying to add a new column to an existing table which is not empty.
My changeset looks like this:
changeSet(author: "someCoolGuy (generated)", id: "1326842592275-1") {
addColumn(tableName: "layer") {
column(name: "abstract_trimmed", type: "VARCHAR(455)", value: "No text") {
constraints(nullable: "false")
}
}
}
Which should have inserted the value 'No text' into every existing row, and therefore satisfied the not null constraint. Liquibase "Add Column" docs.
But when the migrations changesets are being applied I get the following exception:
liquibase.exception.DatabaseException: Error executing SQL ALTER TABLE layer ADD abstract_trimmed VARCHAR(455) NOT NULL: ERROR: column "abstract_trimmed" contains null values
Which looks to me like it is not using the 'value' attribute.
If I change my changeset to work look like the following I can achieve the same thing. But I don't want to (and shouldn't have to) do this.
changeSet(author: "someCoolGuy (generated)", id: "1326842592275-1") {
addColumn(tableName: "layer") {
column(name: "abstract_trimmed", type: "VARCHAR(455)")
}
addNotNullConstraint(tableName: "layer", columnName:"abstract_trimmed", defaultNullValue: "No text")
}
Is Liquibase really ignoring my value attribute, or is there something else going on here that I can't see?
I am using Grails 1.3.7, Database-migration plugin 1.0, Postgres 9.0
Short answer
The "value" attribute will not work if you are adding a not-null constraint at the time of the column creation (this is not mentioned in the documentation). The SQL generated will not be able to execute.
Workaround
The workaround described in the question is the way to go. The resulting SQL will be:
Add the column
ALTER TABLE layer ADD COLUMN abstract_trimmed varchar(455);
Set it to a non-null value for every row
UPDATE table SET abstract_trimmed = 'No text';
Add the NOT NULL constraint
ALTER TABLE layer ALTER COLUMN abstract_trimmed SET NOT NULL;
Why?
A column default is only inserted into the column with an INSERT. The "value" tag will do that for you, but after the column is added. Liquibase tries to add the column in one step, with the NOT NULL constraint in place:
ALTER TABLE layer ADD abstract_trimmed VARCHAR(455) NOT NULL;
... which is not possible when the table already contains rows. It just isn't smart enough.
Alternative solution
Since PostgreSQL 8.0 (so almost forever by now) an alternative would be to add the new column with a non-null DEFAULT:
ALTER TABLE layer
ADD COLUMN abstract_trimmed varchar(455) NOT NULL DEFAULT 'No text';
The manual:
When a column is added with ADD COLUMN and a non-volatile DEFAULT is
specified, the default is evaluated at the time of the statement and
the result stored in the table's metadata. That value will be used for
the column for all existing rows. If no DEFAULT is specified, NULL is
used. In neither case is a rewrite of the table required.
Adding a column with a volatile DEFAULT or changing the type of an
existing column will require the entire table and its indexes to be
rewritten. As an exception, when changing the type of an existing
column, if the USING clause does not change the column contents and
the old type is either binary coercible to the new type or an
unconstrained domain over the new type, a table rewrite is not needed;
but any indexes on the affected columns must still be rebuilt. Table
and/or index rebuilds may take a significant amount of time for a
large table; and will temporarily require as much as double the disk space.
Use "defaultValue" instead of "value" to set a default value for the new column.
To do this in two steps:
Add the column with the value you want on all existing columns as the defaultValue for the column.
changeSet(author: "someCoolGuy (generated)", id: "1326842592275-1") {
addColumn(tableName: "layer") {
column(name: "abstract_trimmed", type: "VARCHAR(455)", defaultValue: "No text") {
constraints(nullable: "false")
}
}
}
Then drop the defaultValue from the column:
changeSet(author: "someCoolGuy (generated)", id: "1326842592275-2") {
dropDefaultValue(tableName: "layer" columnName: "abstract_trimmed")
}
One advantage to this is that if you have a non-static value as what you want entered into the column, it computes it once and uses that to fill all the existing rows (example: a time stamp), rather than possibly recalculating it for each row change.
I have a table called _field. Now, for some reason, a field inside the table called block got messy and now contains the wrong block numbers.
I have the default data for _field, but some of the other fields can no longer be at default because of foreign constraints and stuff, so, I can't just restore the default data.
So, for now, I created a new table called tmp_field and populated it with the default _field data.
Now, I need a query that takes the data from _field and changes all of the block numbers in _field to match the block numbers from tmp_field.
Another way to phrase it would be:
It checks each row of _field and if some field (like fieldid or name) matches the same field in tmp_field, then it changes the value of block in _field to match the value of block in tmp_field.
Note: I am using Postgresql 9.1.
Thanks for everything.
UPDATE _field
SET block = tmp_field.block
FROM tmp_field
WHERE _field.fieldid = tmp_field.fieldid
OR _field.name = tmp_field.name
I'm hoping this is a simple goof I did on my end ...
I have a table in my database set up like so:
column name: widget_guid
data type: uniqueidentifier
allow nulls: false
default value: newid()
identity: false
row guid: true
When records are created (via LINQ to SQL) that the values in this field are formatted as a GUID but contain all 0's
My assumption was that when a new record was created, that a guid would be autogenerated for that column, much like an auto-incrementing row id. Is this not true? Any help would be greatly appreciated.
Thanks.
You need to check your properties on the GUID column - what you need to make sure is:
Auto Generated Values is set to True (so you basically tell Linq-to-SQL that the database will generate the value)
Auto-Sync should be set to OnInsert so that your C# object will be populated with the new value after you've called context.SubmitChanges()
With these two settings, you should get the expected behavior: no need to set the GUID on the client side, the database will generate a new value and insert it, and you'll get it back right after the call to .SubmitChanges()
In your dbml file, set the field to nullable.
If it is set to not-nullable, LINQ does not go as far as checking that the field has a default; it simply believes the field non-nullable and will send Guid.Empty causing the 0's.