I'm developing a personal project with grails in order to learn this powerful tool.
I have encountered this problem when adding two new fields (x,y) to my domain class "Post":
class Post {
long id;
Date creationDate;
String text;
byte[] image;
Style style;
long likeCount;
long dislikeCount;
User owner;
//coordinates on the wall
int x;
int y;
//this is probably to remove
static hasMany = [judgment : Judgment];
static constraints = {
text(nullable:true, maxSize:5000);
image(nullable:true, maxSize:1000000);
creationDate(nullable:true);
x(nullable:true);
y(nullable:true);
}
}
I added x and y after I create some data (Post records) on my postgres database.
But when I run-app in grails console this error comes up:
| Error 2012-03-04 12:04:23,670 [pool-5-thread-1] ERROR hbm2ddl.SchemaUpdate - Unsuccessful: alter table post add column x int4 not null
| Error 2012-03-04 12:04:23,672 [pool-5-thread-1] ERROR hbm2ddl.SchemaUpdate - ERROR: column "x" contains null values
this is very strange because i declared in constraint x,y to be nullable.. so why grails try to alter my table declaring x and y to be not null?
They're primitive int fields, so nullable doesn't make sense. You can't store a null value in the class instance, and if you have a null value in the database there's no sensible default conversion to an int value. You may consider 0 a sensible value for null, but 0 and null aren't equivalent in general.
If you want to allow null values for primitive numbers (int, long, etc.) or for boolean use the non-primitive Object classes Integer, Long, Boolean, etc. Another problem with primitive types is validation. Since they default to 0 (or false for boolean) you can't know whether the user chose 0 or false or if they didn't make a choice at all and you just have the default values from the constructor. So making them non-primitive leaves them null and you can know whether they made a choice or not.
Also, unrelated - you don't need to declare the id field, since Grails adds one for you anyway. And lose the semicolons ;)
Related
Working on a patch for some issues in the Dart Analyzer, I need to understand whether Null itself is considered a nullable type.
Currently, the least upper bound computed by Dart’s type algebra for String and Null is String.
However, in my opinion, the type union of String and Null is a nullable String.
Ticket with patch: https://github.com/dart-lang/sdk/issues/38585 Note that the patch still has a bug in widening T to T? if a closure returns both T and null.
Bonus question (ticket https://github.com/dart-lang/sdk/issues/38623): Is Null itself a nullable type and should be suffixed with ‘?’?
My opinion as proof by contradiction (LUB is least upper bound function):
Assume that Null is not nullable.
That means Null and Null? are different types.
LUB(T, Null) = T?, i.e. combining T with Null widens T to T?
Hence, LUB(Null, Null) = Null?
That violates LUB being reflexive which would mean that LUN(Null, Null) = Null
Hence the assumption is wrong.
Dart does not, yet, have non-nullable types. So, the type written as String is a nullable string. The Null type is considered a subtype of any type, and therefore the least upper bound of Null and (nullable) String is (nullable) String.
When Dart gets non-nullable types, that will change. Then the type written String will be non-nullable, and String? will be nullable, and the least upper bound of Null and String should then (hopefully!) be String?. Non-nullable types are not yet available, but they are being designed and are expected to be released ... well, when they are ready.
If you are trying to patch the Dart Analyzer, then you need to be aware of both type systems at the same tiem, because the analyzer has already been modified to recognize some non-nullable types if you pass the proper flags and proper source code.
I am just doing my first steps with EF CodeFirst, especially with dataAnnotations.
Now I'm doing my best to understand the "DatabaseGenerated" attribute.
What I know so far:
using this attribute gives me three options to handle creation of a property value: Computed, Id and None.
using this attribute means, that the property can not be updated manually - it is done by the database
So - as I can imagine what happens when using th "Id" option, I have no idea what happens when using "Computed" option. I red that this should tell the db to compute the field value.
For example: field "sum" = field "price" + field "shipping".
But how can I use that in that way? I looked around and did not find any examples. Could you please help me?
You can't use EF to tell the database how to compute the column -- you can only tell EF that the column is database generated so it should be retrieved from the database for your use in code.
To control how the database computes the column you have to manually instruct it either outside of EF or in your database initialization logic.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
context.Database.ExecuteSqlCommand("RAW SQL HERE");
}
Your SQL (MS T-SQL) might look like this (more here):
CREATE TABLE t2 (a int, b int, c int, x float,
y AS CASE x
WHEN 0 THEN a
WHEN 1 THEN b
ELSE c
END)
For SQL here's some info about Computed Colums:
http://msdn.microsoft.com/en-us/library/ms191250(v=sql.105).aspx
Also for reference:
http://msdn.microsoft.com/en-us/library/gg193958.aspx
I have a method in order to get data out of a database for a propel-based symfony-1.1 project.
Now the use-case arrived to store an integer into a varchar field, which results in a wrong order, e.g. {1, 17, 5}, and not the numeric one I was expecting, i.e. {1, 5, 17}.
I know that one way would be to redesign my schema.yml, but this is not an option. I was wondering if there is a way to cast said varchar field as an integer without harming the propel-approach.
This is the sorting function:
public static function getFooData($column = 'FooPeer::ID', $orderBy = 'asc') {
//FIXME: Sort varchar fields as integer, needed for FooPeer::REQUESTS
$c = new Criteria();
if ($orderBy == 'asc') {
$c->addAscendingOrderByColumn($column);
} else {
$c->addDescendingOrderByColumn($column);
}
return FooPeer::doSelect($c);
}
What about:
$c->addAscendingOrderByColumn('CAST('.$column.' AS UNSIGNED)');
Just for interest, you could also have written a view for this, and build your model on top of the view rather than the table. Assuming you're writing to the table with Propel, this solution requires the platform to support writable views (I'm not sure they all do, but perhaps that assumption is out of date).
This is often a good/quick technique where you're not sure how to do something in Propel, or where it is really awkward. It's saved me a few times, even though it's not every purist's cup of tea.
I have an existing database that I can't change. I have a column of type int that has various numbers that mean something.
This something would be a string. For example, 1="dog", 2="cat", 3="bird". There are a dozen or so integers to deal with.
I'm using ASP.NET MVC 3 with EF 4.1 and have a WebGrid binding to the Model. Is there a way to alias the data for these integers listed in the WebGrid to display the string value that mean something to the user?
Any help on this would be greatly appreciated!
Add an enum to your Model:
public enum foo
{
dog = 1, cat, bird //etc
}
Hopefully, you are using ViewModels. If you are, add a property for the enum:
public foo thing {get;set;}
And set the value of thing based on the integer value you get from the database:
Model m = new Model{number = 3};
m.thing = (foo) m.number;
Or you could create a helper and use that within the format parameter to set a value based on the integer, or you could use JavaScript/jQuery to alter the values from ints to strings once they have been rendered to the browser.
Say, I have a table in the DB defined as follows
Table: Foo
PkId - int, primary, autoincrement
Bar - int, allow null=false, no default
Now when generating the EF model from the database the 'Bar' field is correctly defined as Nullable=false, Type=Int32.
Now when I do the following
var foo = new Foo();
context.AddToFoos(foo);
context.SaveChanges();
The row is inserted into the database and 'Bar' has a value of 0? I would have expected an exception because Bar hasn't been set. I realise that 0 isn't null but its also not a value that I've set.
Is this by design or have I misunderstood something?
It's not nullable and thus an int. The default of int is 0. So the DB is happy and the framework is fine as well.