I´m trying to update a MySql Database field to an automated datetime field using Migrations.
Here is the code:
public partial class AutomatedDateField : DbMigration
{
public override void Up()
{
this.AlterColumn("Orders", "Created", c => c.DateTime(nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"));
}
Using SQL Server i would use GETUTCDATE() in defaultValueSql. What should i use in this case?
You can't use function as default value for column in MySQL.
Possible solution can be found here: Can I use a function for a default value in MySql?
Related
I would like to add new column in my existed table using domain class but it is not happening. if I use create-drop in application.yml file then it works but at the same time I lost my data. I needed to keep the data as well as I needed to add new column by updating domain class property in grails 3.3.0 and SQL Server 2012
package com.alumni
class Student
{
String studentId
String studentName
String age
static constraints = {
}
}
Database is not updating with column address
It's unclear from your code snippet, but it sounds like you're trying to add
String address
Note that columns are made NOT NULL by default, so if data exists in the table, it's attempting to add a non-nullable column, with null data on every row, so the column will fail to create. You need to allow this column to be nullable in the constraints block as well
static constraints = {
address(nullable: true)
}
If you add that, the column should create successfully.
I am using EF code first approach. I need to rename my PK column name.
public class classname
{
[Key]
public int OldId { get; set; }
}
I need to change OldId to NewId. I tried renaming my OldId to NewId, I tried updating my database with Migration but that didn't help.
I tried renaming both in column name and model and again when I tried to update my database I still get error.
How can I rename my primary Key column without losing its data?
Is the question that OldId is not used in your code anymore but is still in your database, or is your problem that it OldId is in your code but has a different column name in your database?
You can use fluent API or data annotations if you want to tell entity framework that the name of property in your DbSet has a different column name in the database:
Fluent API Method
public class MyDbContext : DbContext
{
public DbSet<ClassName> ClassNames {get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Tell entity framework that you are now building ClassName:
var classNameConfig = modelBuilder.Entity<ClassName>();
// ClassName has an int primary key in OldId:
classNameConfig.HasKey(className => className.OldId);
// "columnX" in the database corresponds with property OldId
classNameConfig.Property(className => className.OldId)
.HasColumnName("columnX");
}
}
Of course in this specific example this can be concatenated into one statement.
The nice thing about fluent API is that you disconnect your classes from the actual database representation. This hides how the actual database names its columns, column order, min size, max size etc from the user of the DbSets.
Just specify a different DbContext, and you can use the same classes with a different Db.
For instance, if you want to use the same entity framework classes in different databases:
class BaseContext : DbContext
{
public DbSet<MyClass> MyClasses {get; set;}
}
// context to be used with database X:
class DataBaseXContext : BaseContext
{
protected override void OnModelCreating(
DbModelBuilder modelBuilder)
{
// I want to use "columnX" for property A, which is optional:
modelBuilder.Entity<MyClass>
.Property(p => p.A)
.HasColumnName("columnX")
.IsOptional();
}
}
// context to be used with database Y:
class DataBaseXContext : BaseContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// I want to use "columnY" for property A, which is required:
modelBuilder.Entity<MyClass>
.Property(p => p.A)
.HasColumnName("columnY")
.IsRequired();
}
}
Data Annotations Method
If you are absolutely sure you want your classes to be used in only one database, with one pre-defined model, you could use Data Annotations.
However, your question shows that it is not uncommon that the same classes will be used in a different database model. So, although this method is very commonly used, I urge you to reconsider a decision to use Data Annotations.
public class classname
{
[Key]
[Column("ColumnX")]
public int OldId { get; set; }
}
changing the Identity column may lead to instability and you cant change anything with the column unless you kill all the Key constraints (all table relation ship)
t will be tooo complicated i would advice you that if data isnt Important then just delete the database and re run migraions it will recreate the database again
The name of the entity property can be different from the name of the database column.
If you need to change the name of the column on the database you can do it with the DBMS manager (SQL Server Enterprise Manager if you are using SQL Server) or running the proper DDL statement (sp_rename on SQL Server) then set the new column name on the property using the attribute ColumnAttribute
[Column("NewId")]
[Key]
public int OldId { get; set; }
If you need to change the name in the code but not on the database you can do a similar thing
[Column("OldId")]
[Key]
public int NewId { get; set; }
In this case you should do a refactor (rename with F2 if you have standard visual studio Keys or Ctrl+R, R if you are using resharper)
If you need to change both you can do both.
I got the following class in my models
public DateTime DateTimePosted { get; set; }
and it's causing this error while DB migrations
"Cannot insert the value NULL into column 'DateTimePosted"
but when I allow nulls in my model this way
public DateTime? DateTimePosted { get; set; }
then migration is succesfull , but column in Db stays nullable,
but when I'm trying to pass it to Db by Seed method it works fine.
This is my controller
public ActionResult AddApartment()
{
return View(new Apartment { DateTimePosted = DateTime.Now });
}
My question is
How to pass to DB date and time of posted data
You get this error because you are trying to add new non-nullable column on a table that already contains some data. Because you're adding a non-nullable column, DB Migrations doesn't know which value to set for the new column to thos already inserted lines into your table. To fix that you have two solutions:
Making DateTimePosted a nullable data by using DateTime?
Modify your newly generated migration file by locating the line that add your new column and add set the defaultValueSql parameter like below :
The code:
AddColumn("YOUR_TABLE_NAME", "DateTimePosted",
c => c.DateTime(nullable: false, defaultValueSql: "GETUTCDATE()")
);
I have a web application with local database in production environment. In new build I decided to change database and added database migration.
I ran Enable-Migrations in NuGet console.
Program has generated 201410141412423_InitialCreate.cs file as I already had database - there're some code that initialize my database schema.
Then I added one field in model Workstation
public class Workstation
{
public int Id { get; set; }
[StringLength(15)]
public string Name { get; set; }
public DateTime LastCall { get; set; } //this field was added
public string UserConfiguration { get; set; }
private readonly ICollection<StatusBase> _statuses = new Collection<StatusBase>();
public virtual ICollection<StatusBase> Statuses
{
get { return _statuses; }
}
}
I ran Add-Migration WorkstationLastCallAdded command in NuGet console. New file with migration logic was generated with next code:
public partial class WorkstationLastCallAdded : DbMigration
{
public override void Up()
{
AddColumn("dbo.Workstations", "LastCall", c => c.DateTime(nullable: false));
}
public override void Down()
{
DropColumn("dbo.Workstations", "LastCall");
}
}
I also added next code in Global.asax file to update my database
protected void Application_Start()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppDbContext, MigrationConfiguration>());
}
Then I build it and run, and everything works fine.
When I deploy new build to server, there's a database file with some data on the server. The database has old scheme - without LastCall field. So I expect migration updates my database and I won't loose any data.
When I run my site after deploy - everything works fine. Data is not lost and database is updated correctly.
If I restart server or IIS and run my site again - I've got an error.
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
When I open local db and watch _MigrationHistory table - there're two rows with 1410151540264_InitialCreate and 201410141956597_WorkstationLastCallAdded migration id's.
Could anybody help me please? Any ideas what's going wrong? Why it works correctly on first run after update but fails on the second?
Thank you in advance.
IIRC, the answer it pretty simple. You have two migrations:
201410151540264_InitialCreate
201410141956597_WorkstationLastCallAdded
You InitialCreate miration is newer than WorkstationLastCallAdded migration. Why? Because InitialCreate is implicitly added to _MigrationHistory table when your DB is created for the first time and you have no migrations. The timestamp for InitialCreate in this case is, of course, equal to current server time. WorkstationLastCallAdded, on the other hand, has a fixed timestamp which reflects the time when you ran Add-Migration WorkstationLastCallAdded command. Therefore, if you create a database after you've created WorkstationLastCallAdded, InitialCreate will be the 'newest' migration.
What happens next? Db initializer searches for the newest migration and finds InitialCreate. Then it compares InitialCreate model hash with current model hash and sees that these hashes are different (of course they are, you have changed your model!). And then you got your error.
The easiest way to solve this is to rename your WorkstationLastCallAdded timestamp (in migration designer file) to something like this:
99999999999999_0001_WorkstationLastCallAdded
A bunch of nines ensures that this migration is older than InitialCreate. 0001 reflects the order of migration. If you want to create another migration, you should name it like this:
99999999999999_0002_SomeOtherFieldAdded
Hope this helps!
I'd like to version a grails domain class by DateTime such that:
each primary ID + DateTime property results in a new DB row (i.e. a new DB row per version)
the newest version can be found without having to specify the DateTime value
My knowledge of grails is a little limited right now and I don't understand how I can achieve this.
Consider the following domain class as an example:
import org.joda.time.DateTime
class Page {
String pageId
DateTime theVersion
String content
static constraints = {
pageId(nullable:false, blank:false, unique:true, matches:"[a-zA-Z\\._-]+")
content(nullable:false, blank:false)
}
static mapping = {
content(type:"text")
}
}
What changes are needed to ensure a new DB row is inserted per version? I'm assuming some form of constraint is required such that pageId+theVersion is unique but I don't know how to express this in the GORM DSL.
How might I get the most recent version without knowing the relevant DateTime value?
I'm envisaging something like:Page.findByPageIdAndTheVersionLessThanEquals('uniquePageId', new DateTime())
I expect this would find many objects not just one. I'd like to be able to also express the equivalent of ORDER BY theVersion DESC LIMIT 0,1
Just create the new versions with new Page(), not with get() - a new record will be inserted.
To assure uniqueness, put into constraints:
theVersion(unique: 'pageId')
Page.findByPageId(pageId, [sort: 'theVersion', order: 'desc', max: 1])
You can utilize Grails' dateCreated implicit timestamping feature - it will even work with joda-time plugin.
OTOH, why don't you utilize Grails' built-in version field? It provides you some features out of box and takes care for optimistic locking.