如何在Asp.Net Core API启动时将数据加载到InMemory数据库中?

时间:2020-10-21 11:56:20

标签: c# asp.net-core entity-framework-core asp.net-core-3.1 ef-core-3.1

我正在研究Asp.Net Core 3.1 API。我在SQL Server数据库中有几个表。

我正在尝试使用InMemory数据库,并且试图在应用程序启动时将数据加载到这些表中。

我写了下面的代码。

public partial class MyContext : DbContext
{
public MyContext ()
{
}

public MyContext (DbContextOptions<MyContext > options)
    : base(options)
{

}

public virtual DbSet<TestEntity> TestEntity{ get; set; }
...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        optionsBuilder.UseInMemoryDatabase("name=RuleDB");
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<MyContext>(opt => opt.UseInMemoryDatabase("myDbName"));

appsettings.json

"ConnectionStrings": {
  "RuleDB": "Server=tcp:xyz.database.windows.net,1433;Initial Catalog=myDB;Persist Security Info=False;User ID=test;Password=****;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30"
}

当我尝试执行context.TestEntity.ToList();时,它没有显示记录。

我基本上是在应用程序启动时尝试将SQL Server数据库中的数据加载到InMemory数据库中。

我是否缺少任何步骤,这不是一个好方法(我是说应该使用InMemory缓存代替InMemory数据库)?

2 个答案:

答案 0 :(得分:-1)

在StartUp.cs中,ConfigureServices引用

services.AddTransient<IEntityRepository, EntityRepository>();
services.AddTransient<IEntityService, EntityService>();    
services.AddMemoryCache();

添加新的存储库界面。

public interface IEntityRepository
{
    Task<List<Entity>> GetEntity();
}

添加一个将封装DbContext的新类,并实现接口

public class EntityRepository : IEntityRepository
{
    private readonly DbContext _dbContext;
    
    public(EntityRepository dbContext){
        _dbContext = dbContext;
    }
    
    public async Task<List<Entity>> GetEntity()
    {
        return await _dbContext.Entity.ToListAsync();
    }
}

添加另一个名为IEntityService的接口

public interface IEntityService
{
    Task<List<Entity>> GetEntity();
}

添加另一个名为EntityService的类,封装缓存和存储库调用。

public class EntityService : IEntityService
{
    private readonly IEntityRepository _repository;
    private readonly IMemoryCache _cache;
    
    public(EntityService repository, IMemoryCache cache){
        _repository = repository;
        _cache = cache
    }
    
    public async Task<List<Entity>> GetEntity()
    {
        var cacheKey = $"{anything-can-be-user-specific-too}";

        return await _memoryCache.GetOrCreateAsync(cacheKey, x =>
        {
            var entities = _repository.GetEntity().GetAwaiter().GetResult();
            x.SlidingExpiration = TimeSpan.FromSeconds(900);
            x.AbsoluteExpiration = DateTime.Now.AddHours(1);

            return Task.FromResult(entities);
        });
    }
}

我以示例为例的缓存策略表明,如果在10分钟内未引用该缓存(slidingRefresh),则该缓存将过期并被删除。可以将它与AbsoluteExpiration一起使用,这样您就可以在假设1小时后强制刷新缓存...

现在让IEntityService成为您的起点,假设您有一个控制器...

将服务注入控制器,例如

 public class RandomController : ControllerBase
    {
        private readonly IEntityService _entityService;

        public RandomController(IEntityService entityService)
        {
            _entityService = entityService;
        }
        
        [HttpGet]
        [Route("randomroute")]
        public async Task<IActionResult> GetEntities()
        {
            return Ok( await _entityService.GetEntity());
        }
    
    }

应用程序第一次执行时将引用数据库,但是所有后续调用(直到缓存策略到期)将引用内存缓存。

现在,如果要更改缓存的项目,可以引入新服务来执行数据库更新,然后通过使缓存键无效来强制进行缓存更新。

Updating IMemoryCache once an entity has changed

答案 1 :(得分:-1)

根据您的代码片段,当应用程序启动时,我没有找到将数据添加到内存数据库的位置。因此,我认为问题与之相关。

尝试引用以下文章将种子数据添加到数据库:

Applying Seed Data To The Database

Using EF Core's InMemory Provider To Store A "Database" In Memory

Entity Framework Core InMemory Database