简体   繁体   中英

Entity Framework 6 Migrations with views

I need to map to a view when using EF6 with migrations.

The view pivots 2 other tables to enable a simple summary view of the underlying data, the idea being it allows us to use this in a summary index view.

The issue I have is I am unable create a migration that either deploys the view (ideal goal) or deploys the DB without the view for later manual deployment.

In most attempts, following other SO questions, I end up either deadlocking the Add-Migration and Update-Database commands or generally causing an error that breaks one or the other.

What is the current best way to use EF6 to access views, even if I lose the ability to automatically deploy them with the migrations, and not cause errors with migrations.

Further detail

The Db contains 2 tables Reports and ReportAnswers. The view ReportView combines these two and pivots ReportAnswers to allow some of the rows to become columns in this summary view.

Reports and ReportAnswers were depolied via EF Migrations. The view is currently a script that needs be added to the deployment somehow.

Reports, ReportAnswers & ReportView are accessible from the db Context

public virtual DbSet<ReportAnswer> ReportAnswers { get; set; }
public virtual DbSet<Report> Reports { get; set; }
public virtual DbSet<ReportView> ReportView { get; set; }

I have tried using Add-Migration Name -IgnoreChanges to create a blank migration and then manually adding the view to the Up() and Down() methods but this just deadlocks the migration and update commands, each wanting the other to run first.

I have also tried using modelBuilder.Ignore<ReportView>(); to ignore the type when running the migrations but this proved incredibly error prone, even though it did seem to work at least once.

I just walked around interesting article about using views with EF Core few days ago, but I found also the very same using EF 6.

You may want to use Seed method instead of migration Up and Down methods.

protected override void Seed({DbContextType} context)
{
    string codeBase = Assembly.GetExecutingAssembly().CodeBase;
    UriBuilder uri = new UriBuilder(codeBase);
    string path = Uri.UnescapeDataString(uri.Path);
    var baseDir = Path.GetDirectoryName(path) + "\\Migrations\\{CreateViewSQLScriptFilename}.sql";

    context.Database.ExecuteSqlCommand(File.ReadAllText(baseDir));
}

Your SQL command should look like sample below.

IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[{ViewName}]'))
EXEC dbo.sp_executesql @statement = N'CREATE VIEW [dbo].[{ViewName}]
AS
SELECT {SelectCommand}

It is not perfect, but I hope at least helpful.

I found another blog post about this topic and the writer says to use Sql(@"CREATE VIEW dbo.{ViewName} AS...") in Up method and Sql(@"DROP VIEW dbo.{ViewName};") in Down method. I added it as you didn't supplied the code from Up and Down migration methods. Maybe good idea will be to add SqlFile instead of Sql method.

There is also option to create customized code or sql generator and plug it in to migrations, but I guess it is not the things you are looking for.

Let me know in comment in case you need additional help.

Related links:

Using Views with Entity Framework Code First

EF CODE FIRST - VIEWS AND STORED PROCEDURES

Leveraging Views in Entity Framework

DbMigration.Sql Method (String, Boolean, Object)

DbMigration.SqlFile Method (String, Boolean, Object)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM