Alter Database in Entity Framework 6 - entity-framework

I have update my EF to EF 6.0.2 in my code I have the following line of code:
applicationDbContext.Database .ExecuteSqlCommand(#"ALTER DATABASE
CURRENT SET RECOVERY FULL;");
After updating I get the following error message:
ALTER DATABASE statement not allowed within multi-statement
transaction.
I have fixed the problem with a TransctionalBehavior like the the code below:
applicationDbContext.Database.ExecuteSqlCommand(
TransactionalBehavior.DoNotEnsureTransaction, #"ALTER DATABASE CURRENT SET RECOVERY FULL;");
My question:
Why I'm getting this error with EF 6?
My fix is a valid fix for the problem or a devil hiding behind this solution?
Is there any other approach to solve the problem?
Any help will be greatly appreciated!?

EF 6 changes the use of transactions with ExecuteSqlCommand
Starting with Entity Framework 6.0, ExecuteSqlCommand() by default will wrap the command in a transaction if one was not already present. There are overloads of this method that allow you to override this behavior if you wish.
EF 5 did not behave the same way. Your fix is appropriate.
You can now specify a TransactionalBehavior flag to instruct EF on how to handle transactions with this command.
var sqlCommand = String.Format("ALTER DATABASE {0} SET SINGLE_USER
WITH ROLLBACK IMMEDIATE");
db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction,
sqlCommand);
By using the DoNotEnsureTransaction flag, EF will not start a transaction before executing the command. This allows the ALTER DATABASE command to successfully execute.

If you are using Code First approach possible solution is
public partial class AlterDatabase : DbMigration
{
public override void Up()
{
Sql("ALTER DATABASE CURRENT SET RECOVERY FULL", true);
}
public override void Down()
{
}
}

Related

Prevent EF from creating a new table during migration

I have an entity for which I don't want a table. The entity is used to generate a report and is populated using a SQL query:
public IEnumerable<Entities.MembersReportRow> Get()
{
return _context.MembersReportRows
.FromSqlRaw(#"
SELECT...")
.ToList();
}
Using modelBuilder.Ignore<MembersReportRow>(); stops the code for creating the table from being added to the migration, but then the method above stops working with error:
Cannot create a DbSet for 'MembersReportRow' because this type is not
included in the model for the context.
I've also tried:
modelBuilder.
.HasNoKey()
.ToSqlQuery(#"
SELECT...
");
...but the code to create the table still gets created in the migration, which surprises me a little as I'm specifically stating "ToSqlQuery".
Any help would be appreciated!

Postgres EF Migrations "3F000: No schema has been selected to create in"

I am attempting to execute an initial database creation migration using entity framework core against a postgres database.
The problem I am having is that I wish to create the tables under a custom schema.
I have managed to create an initial migration with no problems but when I attempt to "update-database" the migration fails with the following error.
Npgsql.PostgresException (0x80004005): 3F000: no schema has been selected to create in
at Npgsql.NpgsqlConnector.<>c__DisplayClass160_0.<g__ReadMessageLong|0>d.MoveNext()
Having initial looked into the issue I assumed this was simply because the schema was not being set in the context.
To get around this I set added the following code to the DbContext
protected override void OnModelCreating(ModelBuilder builder)
{
//Set the default schema
builder.HasDefaultSchema("ConfigStore");
//Continue with the call./Migrate
base.OnModelCreating(builder);
}
I still get the same error when running update-database.
I checked the initial migration Up() method and can clearly see the following code:
migrationBuilder.EnsureSchema(name: "ConfigStore");
The migration creates the database but nothing else so I assume the problem here is that the schema is not being created after the database which is then subsequently causing the table creations to fail.
The question I have is how do I fix this?
Can I execute some custom sql AFTER the database has been created but before the tables? Is there something I can do to get EnsureSchema() to create the schema first?
Thanks in advance
Would you believe it. Hours and hours trying to figure it out and 10 minutes after posting on stack overflow I find the solution....
The problem was the initial connection string. I had defined the connection string as follows:
Server=127.0.0.1; port=5432; user id=XXXX; password=XXXX; database=Test; pooling=true; SearchPath=ConfigStore
The problem was the search path. Apparently EF Migrations creates the database perfectly with this connection string but then attempts to access the tables before creating the schema causing the error reported. Removing the search_path from the connection string resulted in the schema being created first, then the tables. Odd - but hey it works.
I have my custom schema kernel. The following search path helped me to resolve the issue
"Host=localhost;Database=test08;SearchPath=kernel,public;Username=postgres;Password=strongPa$$123;"

How to use migration programmatically in Entity Framework Core

So I want to use migrations in a programmatic way, for this I've done something like this.
Seed is an extension method which I've created over StoreContext
StoreContext is my DbContext
internal StoreContext(DbContextOptions options)
: base(options)
{
RelationalDatabaseCreator creator = this.GetService<IDatabaseCreator>() as RelationalDatabaseCreator;
if (!creator.Exists())
{
creator.Create(); ///=> create database
creator.CreateTables(); ///=> create database tables
}
Database.Migrate(); ///=> apply migrations
if (creator.Exists())
{
this.Seed();
}
}
If the database does not exist the when I ran
Add-Migration Initial
all is good (this is only for my first migration)
If I decide to add new migration
Add-Migration Add_Student_FirstName
a new field in Student then I get this PMC exception
There is already an object named 'SomeTableName' in the database.
the SomeTableName that the console complains about is not necessarily the table on which I've added the change.
But if i go into my code and comment the line for
Database.Migrate(); ///=> apply migrations
and run again
Add-Migration Add_Student_FirstName
all is good again (my migration is added to Migrations folder, but I still have to do the migration by hand using the
Update-Database
command)
So what is wrong in what I'm doing, and how should I fix this so that the migration will be applied automatically when i create it ?
Thanks

Code first filetable in SQL Server

Trying to take advantage of the FileTables feature in SQL Server 2012 in my current MVC5 project. Does anyone have any examples of how to create the file table "table" using code first? All of my tables, indexes, etc. are done using code first and I'd like to continue that practice here.
Unfortunately I cannot help you with FileTable, but this example of FileStream (similar thing in many ways) works quite well.
The decision is available here: "WEB API FILE UPLOAD WITH MS SQL SERVER FILETABLE"
https://damienbod.wordpress.com/2014/04/08/web-api-file-upload-with-ms-sql-server-filetable/
You can add custom SQL in a Code First Migration.
Create a migration Add-Migration
Put In some Custom SQL to Enable Filestreams
Update the db with Update-Database
Example migration with custom SQL:
public partial class AddFileStreamMigration: DbMigration
{
public override void Up()
{
var customSql = #"ALTER DATABASE Photos
SET FILESTREAM (NON_TRANSACTED_ACCESS = FULL)
GO
etc...";
Sql(customSql );
}
public override void Down()
{
//Make sure you put in roll back SQL too!
}
}
```

EF Code First migrations - how to add seed to my migration?

I already have few migrations, and now I am adding another migration, but this time I want to add seed to it. I tried adding this near my Up() and Down() methods:
protected override void Seed(ScykDb context)
{
}
But my compiler says I cannot do that. How can I add seed to my migration?
Seed is not available per migration, only at the DbContext level.
You can easily get around it by adding a call to Sql() in your Up() method:
Sql("insert into ponies (col1, col2.....");