美文网首页Asp.net core mvc
EF Core自动创建存储过程

EF Core自动创建存储过程

作者: firechun | 来源:发表于2019-06-12 09:29 被阅读0次

EF Core创建和迁移数据库都非常方便,比EF6的体验更好。

虽然EF Core为我们提供了非常好用的ORM,但很多时候我们可能仍然需要使用存储过程。很遗憾的是,我没有在EF Core的文档中找到在创建数据库的同时创建存储过程的方法,只能在EF Core创建数据库后手动创建和更新存储过程,这在项目初始阶段搭建和验证数据结构时非常烦琐。因为这个阶段往往会反复修改和迁移数据库,为了保证数据库迁移历史的“干净“,通常迁移时都会删除数据库重新创建,这又不得不重新创建存储过程。

下面看看如何使用EF Core在项目启动时自动创建存储过程

在项目中添加一个目录:StoreProcedure,把创建存储过程的脚本添加到该目录下,可以保存为文本文件。注:如果保存为sql脚本文件(后缀名为sql),VS2017会用sql server的语法校验文件,我用的是mysql数据库,会出现很多语法错误提示。
选择这个脚本文件,打开“属性”面板,按照图示把“复制到输出目录”改为“如果较新则复制”,把“生成操作”改为“嵌入的资源”,当项目发布时,StoreProcedure目录和脚本文件就会发布到服务器上。


image.png

如果有多个存储过程,每个存储过程的脚本保存为单独一份文件,并且把“复制到输出目录”改为“如果较新则复制”,“生成操作”可以不变。实际上“生成操作”只要在首次发布时改为“嵌入的资源”就可以了,即使以后改为默认值“无”,也没关系,而且目录下只要有一份文件设置为“嵌入的资源”,该目录下的所有文件都会发布的服务器上。
存储过程脚本示例(MySql):

DROP PROCEDURE IF EXISTS `GetMembers`;

CREATE DEFINER=`root`@`%` PROCEDURE `GetMembers`()
BEGIN
    SELECT * FROM Member;
END;

接下来添加一个新类:SeedData,在EF Core的教程中用这个类来进行数据初始化,我们把创建存储过程的方法也放到这个类中。
添加方法:

public static async Task CreateStoreProcedure(IServiceProvider serviceProvider)
{
    //BowlContext是EF Core数据上下文
    using (BowlContext context = new BowlContext(
        serviceProvider.GetRequiredService<DbContextOptions<BowlContext>>()))
    {
        var path = $"{AppContext.BaseDirectory}StoreProcedure";
        var files = Directory.GetFiles(path);
        foreach(var filename in files)
        {
            string script = File.ReadAllText(filename);
            await context.Database.ExecuteSqlCommandAsync(script);
        }
    }
}

代码很简单,读取StoreProcedure目录下所有文件,并将每个文件中的内容做为脚本在数据库中执行。
修改项目的Program.cs文件中的启动方法Main

public static void Main(string[] args)
{
    var host = CreateWebHostBuilder(args).Build();
    using (var scope = host.Services.CreateScope())
    {
        var service = scope.ServiceProvider;
        try
        {
            var context = service.GetRequiredService<ShunShiContext>();
            context.Database.Migrate();
            //初始化数据
            SeedData.Initialize(service).Wait();
            //创建存储过程
            SeedData.CreateStoreProcedure(service).Wait();
        }
        catch (Exception ex)
        {
            var logger = service.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "数据库初始化错误!");
        }
    }
    host.Run();
}

在本地调试时,程序每次启动都会自动删除旧的存储过程,创建新的存储过程。发布后也会执行一次创建存储过程的代码。这就达到了自动创建和更新存储过程的目的。
如果觉得本地调试每次启动都会更新存储过程不太好的话,也可以修改一下CreateStoreProcedure方法,做到有条件更新,比如增加一个更新清单,只更新清单中列出的存储过程等等,方法很多,不再赘述了。

相关文章

网友评论

    本文标题:EF Core自动创建存储过程

    本文链接:https://www.haomeiwen.com/subject/vlhcfctx.html