Trigger and Stored Procedure Management with EF Core

Trigger and Stored Procedure Management with EF Core


We ran our tests using MySQL.

You can use the following command to list your current Triggers.

select * from information_schema.TRIGGERS

You can use the following command to list the available Stored Procedures.

select * from information_schema.ROUTINES

Here are your active scripts in your database. Some are built by default and are used for your system needs. You can expand the following queries to filter only scripts you have created.

select * from information_schema.TRIGGERS where TRIGGER_SCHEMA = 'your_schema'
select * from information_schema.ROUTINES where ROUTINE_TYPE = 'PROCEDURE' and ROUTINE_SCHEMA = 'your_schema'

You've seen how we filter our data. If you want old scripts to be renewed when you make changes to these parts in the future, I have developed a trick for you. You can put this process in a method and then trigger it in public void Configure(IApplicationBuilder app) method in Startup.cs. Thus, every time the project is up, it will replace the old scripts with new ones. Evaluate this triggering need carefully according to the risk situation of the project!

            var listTriggers = new List<string>();
            var listStoredProcedures = new List<string>();
            using (var command = _context.Database.GetDbConnection().CreateCommand())
            {
                command.CommandText = "select group_concat(TRIGGER_NAME) from information_schema.TRIGGERS where TRIGGER_SCHEMA = 'your_schema'";
                command.CommandType = CommandType.Text;
                _context.Database.OpenConnection();
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var value = reader[0].ToString();
                        if (!string.IsNullOrEmpty(value))
                            listTriggers.AddRange(value.Split(","));
                    }
                }

                command.CommandText = "select group_concat(ROUTINE_NAME) from information_schema.ROUTINES where ROUTINE_TYPE = 'PROCEDURE' and ROUTINE_SCHEMA = 'your_schema'";
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var value = reader[0].ToString();
                        if (!string.IsNullOrEmpty(value))
                            listStoredProcedures.AddRange(value.Split(","));
                    }
                }
            }

            foreach (var item in listTriggers)
                _context.Database.ExecuteSqlRaw($"drop trigger if exists {item}");

            foreach (var item in listStoredProcedures)
                _context.Database.ExecuteSqlRaw($"drop procedure if exists {item}");

            var sqlFiles = new List<string> {"fnc", "stp", "trg"};
            foreach (var sqlFile in sqlFiles)
            {
                var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Scripts", $"{sqlFile}.sql");
                var sql = File.ReadAllText(path);
                if (!string.IsNullOrEmpty(sql))
                    _context.Database.ExecuteSqlRaw(sql);
            }

Finally, I added Functions (fnc.sql)/Stored Procedure (stp.sql)/Trigger (trg.sql) under the Scripts folder by grouping them in separate folders. When the above code block runs, all stored procedures and triggers that match the filters will be deleted and the queries under the Scripts folder will be run and loaded again.

For example, the contents of the trg.sql file

create trigger trg_blogpost_view_count_after_update_user
    after update
    on blog_posts
    for each row
begin
    if (OLD.ViewCount + 1 = NEW.ViewCount) then
        update users set BlogPostViewCount = BlogPostViewCount + 1 where Guid = OLD.CreatedBy;
    end if;
end;

An error has occurred. This application may no longer respond until reloaded. Reload 🗙