EF6 Oracle default value for a column in code first migration - oracle

I am trying to write a migration that sets Default Value for a NUMBER column in my Oracle database using EntityFramework 6. Here is my first try that didn't set the default value:
public override void Up()
{
AddColumn("MTA.PLAN_SHEETS", "QUANTITY_CHANGED", c => c.Decimal(nullable: true, precision: 3, scale: 0, defaultValueSql: "1"));
}
I also tried to use defaultValue instead of defaultValueSql and again it didn't set the default value for the column.
Is there anything wrong with my migration code?

I came across the same problem working with Oracle and EF6. It would appear the Oracle provider does not support it. There is a work around though, in case you haven't already found one.
You first need to set the QuantityChanged property as nullable in your model (or Fluent API, wherever you are handling this). Then you can run the add-migration command which will generate a migration file with the 'AddColumn' method in the 'Up' method. After that, add an explicit SQL command to update all values to the default value needed. If you need the column to be NOT NULL moving forward you will need another SQL command to modify the column and set it to NOT NULL.
public override void Up()
{
AddColumn("MTA.PLAN_SHEETS", "QUANTITY_CHANGED", c => c.Decimal(precision: 3, scale: 0));
Sql("UPDATE MTA.PLAN_SHEETS SET QUANTITY_CHANGED = 1");
Sql("ALTER TABLE MTA.PLAN_SHEETS MODIFY QUANTITY_CHANGED NOT NULL");
}
I hope this helps. Reference my question if needed: How do I set a default value for a new column using EF6 migrations?

Related

Laravel Sqlite column index out of range

When running tests using phpunit I'm getting a not so nice exception
SQLSTATE[HY000]: General error: 25 column index out of range (SQL: select count(*) as aggregate from "attachments" where "id" = f3bad3ad-a888-41bc-b6fd-9a5998f6b527
The Attachment.Id is a UUID and the column is defined as primary key. When running the tests I am using SQLite with an in-memory db.
When switching over to MySQL I do not get an error anymore. I don't really know why the query would cause an error.
Any tips?
1) Make sure the property public $incrementing = false; is set on the model.
2) The migration should be $table->uuid('id')->primary();
3) Add the below function to the model:
public function getKeyType()
{
return 'string';
}
4) To diagnose, create a database.sqlite and allow the test to run on that DB. Diagnose the size of the ID column. Does it fit the UUID string? If it actually doesn't, you may have to update your Laravel app or edit your migrations so if it's running on Sqlite, it will create a string column with the appropriate length.

Scaffolding an Oracle table without an ID column in Grails

I'm creating a Grails 3 app with some tables from my Oracle 12c database scaffolded and while so far everything went fast, I came across one problematic table which doesn't have an ID column. It's just four VARCHAR2's. Also, in the Constraints tab of the Oracle SQL Developer, I don't see any of them defined as the Primary Key. How should one progress in such a scenario to successfully create a CRUD for this class?
I've tried telling Grails to use the row id as an ID but this only results in a "getLong not implemented for class oracle.jdbc.driver.T4CRowidAccessor" error when I try accessing the (to-be) scaffolded page. My code looks like this:
class AliasFrequencyDict {
String frequency
String unit
String description
String lang
static constraints = {
frequency maxSize: 10, sqlType: 'VARCHAR2'
unit maxSize: 1, sqlType: 'VARCHAR2'
description maxSize: 30, sqlType: 'VARCHAR2'
lang maxSize: 2, sqlType: 'VARCHAR2'
}
static mapping = {
sort 'frequency'
version false
id column: 'ROWID'
}
}
How should I solve this if I don't have an explicit ID column and I am not allowed to create one?
EDIT: So the only way I was able to progress so far was to use a composite key consisting of all the columns and then manually change the index view so that instead of this:
<f:table collection="${aliasFrequencyDict}" />
we now have this:
<f:table collection="${aliasFrequencyDictList}" properties="['frequency','unit','description','lang']"/>
This, however, doesn't let me access any of the existing entries or add new ones, as I guess I'd have to manually specify these properties there, too. It doesn't seem like it's nearly as easy to explicitly state them in the edit view, for example, as it is in the index, though (or to make the editing actually work, on top of that).
EDIT2: Also, from what I gathered, using ROWID isn't a good idea anyway. Oracle docs state:
Although you can use the ROWID pseudocolumn in the SELECT and WHERE
clause of a query, these pseudocolumn values are not actually stored
in the database. You cannot insert, update, or delete a value of the
ROWID pseudocolumn.
Thus, I'm out of ideas about how to progress :( Any help?

How do I set a default value for a new column using EF6 migrations?

I know that you can manually manipulate the EF generated migration file to add in the 'defaultValue: 1' parameter to the 'AddColumn' method, but it does not seem to be generating the correct Oracle translation when I look at the generated script.
See my EF migration 'Up' method below:
public override void Up()
{
AddColumn("TABLE", "NEW_COLUMN", c => c.Decimal(nullable: false, precision: 10, scale: 0, defaultValue: 1));
}
And after running 'update-database -script' I get the following corresponding SQL line:
alter table "TABLE" add ("NEW_COLUMN" number(10, 0) not null)
Running this against the database will not set the default value of the existing rows to the desired value of 1... What am I missing here?
I am using EF version 6.0.0.0 and Oracle Managed Data Access version 6.121.2.0

ActiveRecord search returns 'Syntax error or access violation' error

In my Yii application, I have a model that represents siteconfig table and have four columns:
integer config_id,
string key,
string value,
string update_time.
I created a model using Gii (to ensure that I will not make any mistakes). I don't publish entire code here, cause this is 100% unmodified by me, standard model code generated by Gii. Since my problem is related to search, I only publish important part of generated code (the search() method):
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('config_id',$this->config_id);
$criteria->compare('key',$this->key,true);
$criteria->compare('value',$this->value,true);
$criteria->compare('update_time',$this->update_time,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
I'm trying to use generated model in normal Yii ActiveRecord search like that:
$etona = new SiteConfigurationRecord();
$crit = new CDbCriteria();
$crit->select = "value";
$crit->condition = "key=:key";
$crit->params = array(":key"=>"sitename");
$etona = $etona->find($crit);
But, instead of getting expected search results, a strange (for me) error occurs:
CDbCommand failed to execute the SQL statement: SQLSTATE[42000]:
Syntax error or access violation: 1064 You have an error in your SQL
syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'key='sitename' LIMIT 1' at line 1.
The SQL statement executed was: SELECT value FROM siteconfig t
WHERE key=:key LIMIT 1
Where did I go wrong?
You used key for column name, which is a reserved word in MySQL. Yii uses table alias in queries, but does not take any special care in case of reserverd word used as columns names. So, you have to take care of this by yourself.
For example:
$etona = new SiteConfigurationRecord();
$crit = new CDbCriteria();
$crit->select = "value";
$crit->condition = "t.key=:key"; // 't' is default alias
$crit->params = array(":key"=>"sitename");
$etona = $etona->find($crit);
This should solve your problem.
As #Dmitry explained, SQL doesn't allow you to use the column name key. The Yii call in the code in your answer works because Yii performs parameter binding automatically, using names other than reserved words for the parameters. And it also uses fully-qualified column names (prefixes all column name references with <tablename>., regardless of what invalid column name (reserved words) you pass the findByAttributes method.
now it works.. ^^
i just use this code...
$etona = SiteConfigurationRecord::model()->findByAttributes(array('key'=>'sitename'));
maybe i need to study activerecord more somehow...
but still i don't know why the code above doesn't work

LINQ not updating on .SubmitChanges()

Is there any reason something like this would not work?
This is the logic I have used many times to update a record in a table with LINQ:
DataClasses1DataContext db = new DataClasses1DataContext();
User updateUser = db.Users.Single(e => e.user == user);
updateUser.InUse = !updateUser.InUse;
db.Log = new System.IO.StreamWriter(#"c:\temp\linq.log") { AutoFlush = true };
db.SubmitChanges();
(updateUser.InUse is a bit field)
For some reason it isn't working. When I check the linq.log it is completely blank.
Could there be a problem with my .dbml? Other tables seem to work fine but I've compared properties in the .dbml and they all match.
It's as if the db.SubmitChanges(); does not detect any updates being required.
The table could not be updated properly because it had no primary key. (Actually it had the column but the constraint was not copied when I did a SELECT INTO my dev table). The DataContext class requires a primary key for updates.
Is the InUse property a "normal" one as far as LINQ is concerned? (e.g. it's not autogenerated or anything funky like that?)
Alternatively, I don't suppose it's a Nullable<bool> is it, with a current value of null? If so, your update line isn't actually doing anything - for nullable Booleans, !null = null.

Resources