Oil g Migration Not Writing Any Queries - fuelphp

Quick Question:
When I run this ...
php htdocs/travel-photo/oil generate migration follow user:string pass:text name:string photo:string email:string
I looked at the migrations folder, this what it shows me ...
namespace Fuel\Migrations;
class Follow
{
public function up()
{
}
public function down()
{
}
}
What could be wrong here?
Thanks.

I Should've read the Documentation more clearly. You need to specify what action you want to do one the migration ... So from what I created:
php htdocs/travel-photo/oil generate migration users user:string pass:text name:string photo:string email:string
I need to add: oil generate migration create_users ...
php htdocs/travel-photo/oil generate migration create_users user:string pass:text name:string photo:string email:string
http://docs.fuelphp.com/packages/oil/generate.html#migrations

I see this going in one of two ways: (i) either generate a model using oil and have the migration auto-generated, or (ii) use a magic-named migration.
For option (i), use oil generate model and the rest should be pretty obvious - oil generates the migration as well as the model.
For option (ii), the magic-name tells oil what you are trying to accomplish with the migration, so you can create tables, add columns, drop tables, or pretty much anything else supported by oil, simply by defining a name that oil can interpret as one of these operations.

Related

Entity Framework Code First post migration step?

Is there some way to add a post migration method to Code First EF migration?
All the stored proc's are in the Visual Studio project. Right now there is an approach to load the stored proc resource from the file and put it into it's own migration:
protected override void Up(MigrationBuilder migrationBuilder)
{
var script = ScriptMgr.LoadStoredProc( "StoredProcThatChanged.sql" );
migrationBuilder.Sql( script );
}
There is a weak link in this process: Each time the script changes (StoredProcThatChanged.sql) a new migration needs to be created to make sure it executes again. The problem is the previous migration is also loading the same file. When generating a new script, the process reads in the one file both times, effectively changing the previous migration. Which is a classic no-no.
This would be resolved if there is a post migration method where ALL stored proc's can be reapplied to the DB. Is such a step possible? If so, now is it done?
I have been digging into the efcore source code and it looks like it is possible, not ideal, but there might be a way...
It looks like efcore has an interface called IMigrator. It contains the method string GenerateScript(...). The implementation of it, class Migrator, has comments all over the place saying that it's implementation of GenerateScript is internal and subject to change. But... It looks to me like I can achieve my end goal:
class MyMigrator : Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator
{
public string GenerateScript(
string? fromMigration = null,
string? toMigration = null,
MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default)
{
var result = base.GenerateScript( fromMigration, toMigration, options);
results += MyPostSteps(...);
return results;
}
}
Will this work and does anyone know how I might go about replacing the default Migrator with the MyMigrator?

Django migration would delete important table

SHORT VERSION: Django's migration subsystem seems to want to drop and re-create my table, rather than just adding a column. How can I fix that?
LONG VERSION:
I'd like to add a field to one of my Django 3.0 models. No biggie, right?
add field to the class definition
manage.py makemigrations
manage.py migrate
So there's a strange issue....when I run makemigrations, I see this in the output:
Migrations for 'api':
api/migrations/0006_auto_20200814_0953.py
- Delete model APISearch
[snip]
- Create model APISearch
[snip]
And sure enough, there are instructions in the resulting migrations to delete and then create an APISearch model.
That would be very bad...APISearch is a real table in my database, containing important data.
I think the issue has to do with the fact that a long time ago, APISearch was a proxy class (it has long since been changed to a concrete class). I can't figure out how Django is determining proxy-ness, so that I can correct it.
I think I found the solution.
Edit the migration that originally created the class:
operations = [
migrations.CreateModel(
name='APISearch',
fields=[
],
options={
'proxy': True, # explicitly set this to False
'indexes': [],
},
bases=('foo.search',),
),
]
Create an empty migration, and use the AddField method to do what I want
operations = [
migrations.AddField(
model_name='apisearch',
name='my_new_field',
field=models.NullBooleanField(blank=True, null=True),
),
]

Entity Framework new object vs DbSet.Create

We are migrating a web application from EF 4.0 to EF 6. The entities were earlier based on ObjectContext, but now we are looking at DBContext. The code heavily depends on lazy loading. Entities are added using following syntax:
var user = new EntityModel.User();
user.DepratmentId=25;
context.Users.Add(user);
context.SaveChanges();
var name = user.Department.Name;
the original code would easily assign department name into variable name. After Entity framework upgrade to EF6 with DBContext, user.Department is null. I understand that when we are using DBContext, Lazy Loading works only with Proxies. It would work fine if the code was changed to following:
var user = context.Users.Create();
user.DepratmentId=25;
context.Users.Add(user);
context.SaveChanges();
var name = user.Department.Name;
Problem at my hand is that we can not make this change in the whole code base. Given the large volume of code, this is practically impossible. Does someone have a solution to this?
Provided your entities are easily identifiable such as all being pulled from the namespace "EntityModel" then VS's Find & Replace can help with the transition. Ultimately you're going to have to eat the cost of that technical debt. Re-factoring isn't free, but the benefit from making improvements (beyond just upgrading a dependency version) should outweigh that cost.
Using Find & Replace:
Find: = new EntityModel.(?<class>.*)\(\)
Replace: = context.${class}s.Create()
This will find instances like:
var user = new EntityModel.User();
and replace it with var user = context.Users.Create();
a test with:
var user = new EntityModel.User();
var test = new EntityModel.Test();
var fudge = new EntityModel.Fudge();
resulted in:
var user = context.Users.Create();
var test = context.Tests.Create();
var fudge = context.Fudges.Create();
Now this will extract the class name and pluralize it with an 's' which likely won't match 100% of the entity DBSet names, but those are easily found and corrected. The expressions can be tuned to suit differences through the application and I would recommend performing the operation on a file by file, or at most project by project basis.
An caveat is to make sure you're running with source control so that any bad attempts at a replace can be rolled back safely.

Code First TVF in 6.1.0-alpha1-30113

EF People,
My understanding is that the newly made public APIs for metadata will allow us to add enough metadata in to the model so that TVF can be called and be composable.
If anyone can point me in the right direction I would greatly appreciate it. Without Composable TVF I have to jump through some major work a rounds.
From looking at the unit test it looks like something a long this line of thought:
var functionImport = EdmFunction.Create()
"Foo", "Bar", DataSpace.CSpace,
new EdmFunctionPayload
{
IsComposable = true,
IsFunctionImport = true,
ReturnParameters = new[]
{
FunctionParameter.Create("functionname", EdmType.GetBuiltInType()
EdmConstants.ReturnType,
TypeUsage.Create(collectionTypeMock.Object),
ParameterMode.ReturnValue),
}
});
...
entityContainer.AddFunctionImport(functionImport);
Thanks,
Brian F
Yes, it is now possible in EF6.1. I actually created a custom model convention which allows using store functions in CodeFirst using the newly opened mapping API. The convention is available on NuGet http://www.nuget.org/packages/EntityFramework.CodeFirstStoreFunctions. Here is the link to the blogpost containing all the details: http://blog.3d-logic.com/2014/04/09/support-for-store-functions-tvfs-and-stored-procs-in-entity-framework-6-1/. The project is open source and you can get sources here: https://codefirstfunctions.codeplex.com/

Unique Constraint with Entity Framework using Code First Migrations

I am doing entity framework (v 5) code first migrations, on an MVC 4 application. I would like to add a unique constraint at the database level.
I know this can be done when creating the table, but I already have a table.
http://msdn.microsoft.com/en-US/data/jj591621
I have tried the following, marked as answer answer: Unique constraint with EFCodeFirst and SqlCe4
My database context differes slightly, I supply the connection name is as follows
public AppDatabaseContext() : base("MyConnectionDBContext")
When I use the Package Management Console to update the database, the overridden seed method is not called:
protected override void Seed(AppDatabaseContext context)
I have also tried the following: http://romiller.com/2010/07/31/ef-ctp4-tips-tricks-running-additional-ddl/
I did not use a nested class, this is because it seemed as if I had to registere the initializer via the app.config. I could not get it working while initializing it in code. The InitializeDatabase is called, but the following condition is never true:
(!context.Database.Exists() || !context.Database.ModelMatchesDatabase())
This is because this happens after the migrations have been run...
I also tried this at one stage: Unique Constraint in Entity Framework Code First, it was the same problem as before, this condition was never returning true.
Ideally, I would like to include some standard SQL in my migration file. Is there a way to do that? If not, where can I see how to achieve this with using code first migrations?
Thanks!
UPDATE:
Is there any reason why I can't use the SQL function?
public override void Up()
{
AddColumn("Posts", "Abstract", c => c.String());
Sql("UPDATE Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
}
Obviously using the correct SQL...
With code first migrations, I've just used this in the Up() method to add a unique index on a single column:
CreateIndex(table: "Organisations",
column: "Name",
unique: true, // unique index
name: "MyIndex");
...and then in the Down() method:
DropIndex(table: "Organisations",
name: "MyIndex");
Is that what you're after?
Since EF 6.1 you can now do this in your model with either
an attribute
[Index("IX_UniqueName", IsUnique = true)]
public string Name {get;set;}
or fluent
Property(s => s.Name).HasColumnAnnotation(IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_UniqueName") { IsUnique = true }));
The fluent method isn't perfect as its crazy verbose IMO but at least its possible now.
More deets on Arthur Vickers blog http://blog.oneunicorn.com/2014/02/15/ef-6-1-creating-indexes-with-indexattribute/
You can just scaffold a new migration using the Add-Migration command from your package manager console. Once the empty migration is created, in the Up method, you can use the CreateIndex method of the DbMigration class to create your new index. It would look like something like this: CreateIndex("dbo.Accounts", "AccessKey", unique: true);