Dynamically changing schema in Entity Framework Core

后端 未结 10 2300
刺人心
刺人心 2020-11-28 09:02

UPD here is the way I solved the problem. Although it\'s likely to be not the best one, it worked for me.


I have an issue with working with EF

10条回答
  •  时光说笑
    2020-11-28 09:21

    I actually found it to be a simpler solution with an EF interceptor.

    I actually keep the onModeling method:

      protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.HasDefaultSchema("dbo"); // this is important to always be dbo
    
            // ... model definition ...
        }
    

    And this code will be in Startup:

        public void ConfigureServices(IServiceCollection services)
        {
            // if I add a service I can have the lambda (factory method) to read from request the schema (I put it in a cookie)
            services.AddScoped(provider =>
            {
                var context = provider.GetService().HttpContext;
    
                var scheme = "dbo";
                if (context.Request.Cookies["schema"] != null)
                {
                    scheme = context.Request.Cookies["schema"];
                }
    
                return new SchemeInterceptor(scheme);
            });
    
            services.AddDbContext(options =>
            {
                var sp = services.BuildServiceProvider();
                var interceptor = sp.GetService();
                options.UseSqlServer(Configuration.GetConnectionString("Default"))
                    .AddInterceptors(interceptor);
            });
    

    And the interceptor code looks something like this (but basically we use ReplaceSchema):

    public interface ISchemeInterceptor : IDbCommandInterceptor
    {
    
    }
    
    public class SchemeInterceptor : DbCommandInterceptor, ISchemeInterceptor
    {
        private readonly string _schema;
    
        public SchemeInterceptor(string schema)
        {
            _schema = schema;
        }
    
        public override Task> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result,
            CancellationToken cancellationToken = new CancellationToken())
        {
            ReplaceSchema(command);
            return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);
        }
    
        public override InterceptionResult ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)
        {
            ReplaceSchema(command);
            return base.ScalarExecuting(command, eventData, result);
        }
    
        public override Task> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result,
            CancellationToken cancellationToken = new CancellationToken())
        {
            ReplaceSchema(command);
            return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);
        }
    
        public override InterceptionResult NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)
        {
            ReplaceSchema(command);
            return base.NonQueryExecuting(command, eventData, result);
        }
    
        public override InterceptionResult ReaderExecuting(
            DbCommand command,
            CommandEventData eventData,
            InterceptionResult result)
        {
            ReplaceSchema(command);
            return result;
        }
    
        public override Task> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result,
            CancellationToken cancellationToken = new CancellationToken())
        {
            ReplaceSchema(command);
            return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
        }
    
        private void ReplaceSchema(DbCommand command)
        {
            command.CommandText = command.CommandText.Replace("[dbo]", $"[{_schema}]");
        }
    
        public override void CommandFailed(DbCommand command, CommandErrorEventData eventData)
        {
            // here you can handle cases like schema not found
            base.CommandFailed(command, eventData);
        }
    
        public override Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData,
            CancellationToken cancellationToken = new CancellationToken())
        {
            // here you can handle cases like schema not found
            return base.CommandFailedAsync(command, eventData, cancellationToken);
        }
    
    
    }
    
        

    提交回复
    热议问题