Entity Framework Core Run Custom Scripts

时间:2017-06-19 14:00:29

标签: c# entity-framework-core sql-scripts

Each time my site starts, I want to run X number of scripts. The last thing the Startup.Configure method will do is call my method:

DbInitializer.Initialize(context);

if (env.IsDevelopment()) {
  scopeFactory.SeedData(Configuration.GetConnectionString("AlmanacSQL"));
}

Here is my method:

public static void SeedData(this IServiceScopeFactory scopeFactory, string connectionString) {
  using (var serviceScope = scopeFactory.CreateScope()) {
    var context = serviceScope.ServiceProvider.GetService<AlmanacDb>();

    foreach (var f in di.GetFiles("*.sql").OrderBy(x => x.Name)) {
      context.Database.ExecuteSqlQuery(File.ReadAllText(f.FullName));
    }
  }
}

It works great until it tries to run the first script and fails with:

'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.

I have seen this answer here but that is specific to a Migration. Other answers did not help in my situation. I simply want to run these each time. The scripts will be smart enough to not duplicate what they are doing.

I tried taking out the GO statements and that did not do the trick.

Is there a way to execute SQL Scripts in Entity Framework Core that have GO statements within them? Is there some setting I can swap in SQL or EF? Is there a deeper underlying context like the following that I have used in EF 6?

public ObjectContext UnderlyingContext { get { return ((IObjectContextAdapter)this).ObjectContext; } }

EDIT Right after I got back into my code I figure I should at least show the script:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'GetEnumTriplet') AND type IN (N'P', N'PC'))
  DROP PROCEDURE GetEnumTriplet
GO

CREATE PROCEDURE GetEnumTriplet
(
  @Enumeration NVARCHAR(25),
  @EnumName    NVARCHAR(25) = NULL,
  @EnumValue   INT = NULL
)
AS
BEGIN

  DECLARE @SQL     NVARCHAR(250)
  DECLARE @PDs     NVARCHAR(100) = N'@OutValue INT OUTPUT, @OutDisplay NVARCHAR(30) OUTPUT, @OutName NVARCHAR(25) OUTPUT'
  DECLARE @Value   INT = 0
  DECLARE @Display NVARCHAR(30)
  DECLARE @Name    NVARCHAR(25)

  IF (@EnumName IS NOT NULL)
    SET @SQL = 'SELECT @OutValue = e.ID, @OutDisplay = e.Name, @OutName = e.EnumName FROM ref.' + @Enumeration + ' AS e WHERE e.EnumName = ' + '''' + @EnumName + ''''
  ELSE IF (@EnumValue IS NOT NULL)
    SET @SQL = 'SELECT @OutValue = e.ID, @OutDisplay = e.Name, @OutName = e.EnumName FROM ref.' + @Enumeration + ' AS e WHERE e.ID = ' + CAST(@EnumValue AS NVARCHAR)

  EXECUTE sp_executesql
    @SQL, @PDs, @OutValue = @Value OUTPUT, @OutDisplay = @Display OUTPUT, @OutName = @Name OUTPUT;

  -- Test Content

  SELECT
    1            AS ID,
    @Value       AS Value,
    @Display     AS DisplayName,
    @Name        AS KeyName,
    @Enumeration AS EnumerationName

/*
GetEnumTriplet 'ProjectStatus', 'In Progress' -- Wrong
GetEnumTriplet 'ProjectStatus', 'InProgress', 3 -- Will default to looking up InProgress and skip looking up 3
GetEnumTriplet 'ProjectStatus', 'InProgress'
GetEnumTriplet 'ProjectStatus', NULL, 2
*/
END
GO

0 个答案:

没有答案