【问题标题】:Is there any way to directly query the in memory database used by Entity Framework Core?有没有办法直接查询 Entity Framework Core 使用的内存数据库?
【发布时间】:2020-05-03 12:34:28
【问题描述】:

我正在使用内存数据库提供程序对 .Net Core 2.2 应用程序进行一些测试。我需要使应用程序中的一个表无法访问 - 通过重命名或删除它。有没有办法直接对内存数据库运行这种查询?我尝试使用以下方式建立连接:

context.Database.GetDbConnection();

但这会引发错误

关系特定的方法只能在上下文使用关系数据库提供程序时使用。

我知道我可以使用以下方法破坏整个数据库:

context.Database.EnsureDeleted();

但我需要保留它并且只销毁或重命名一张表。

【问题讨论】:

    标签: c# .net database entity-framework-core


    【解决方案1】:

    InMemory 提供程序不受关系数据库的支持,并且有一组不同的操作不支持您的情况。

    您可以改为使用 SQLite 内存模式 (doc),然后创建一个拦截器来拦截发出的 EF 命令,并禁止创建表,或禁止针对该表的其他查询。

    public class MyInterceptor : DbCommandInterceptor {
        public override InterceptionResult<int> NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<int> result) {
            if (ContainsBannedTable(command)) {
                //suppress the operation
                result = InterceptionResult<int>.SuppressWithResult(0);
            }
            return base.NonQueryExecuting(command, eventData, result);
        }
    
        private bool ContainsBannedTable(DbCommand command) {
            //or custom logic
            return command.CommandText.Contains("ToDeleteEntity");
        }
    }
    

    尝试访问不需要的表时,以下内容将引发异常 (Microsoft.EntityFrameworkCore.DbUpdateException... SqliteException: SQLite Error 1: 'no such table: ToDeleteEntity')。

    var connection = new SqliteConnection("DataSource=:memory:");
    connection.Open();
    var options = new DbContextOptionsBuilder<MyContext>()
                      .UseSqlite(connection)
                      .AddInterceptors(new MyInterceptor())
                      .Options
                      ;
    
    var context = new MyContext(options);
    context.Database.EnsureCreated();
    
    context.AllowedEntity.Add(new AllowedEntity { Id = 1 });
    context.SaveChanges();
    Console.WriteLine(context.AllowedEntity.FirstOrDefault()?.Id); //1 - ok
    
    context.ToDeleteEntity.Add(new ToDeleteEntity { Id = 1 });
    //will throw an exception
    context.SaveChanges();
    Console.WriteLine(context.ToDeleteEntity.FirstOrDefault()?.Id);
    
    //close the connection and clean up
    //...
    
    public class MyContext : DbContext {
        public MyContext(DbContextOptions options) : base(options) {
        }
    
        public DbSet<AllowedEntity> AllowedEntity { get; set; }
        public DbSet<ToDeleteEntity> ToDeleteEntity { get; set; }
    }
    
    public class ToDeleteEntity {
        public int Id { get; set; }
    }
    
    public class AllowedEntity {
        public int Id { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 1970-01-01
      • 2021-08-23
      • 2018-04-01
      • 1970-01-01
      • 2018-08-31
      • 2015-05-25
      • 1970-01-01
      • 2022-10-14
      相关资源
      最近更新 更多