首页 > 解决方案 > 如何在 ASP NET 中将内存数据与磁盘同步

问题描述

在 ASP NET 控制器中,我有一个返回项目列表的服务。该服务从 RAM 将列表提供给请求者。该列表也可以由一组特殊的用户更改,因此每次更改时,我都会将更改写入磁盘并从磁盘更新我的 RAM。(以这种方式阅读我自己的作品)

当我更改此列表时,来自JS客户端的更改已正确写入磁盘,但是当我转发第二个请求以获取我的列表时,我收到了一个陈旧的列表。我需要按 F5 让客户端获取正确的数据.

我不明白 RAM 缓存是如何落后的。您可以在下面的服务中看到我已经用 . 保护了更改方法lock。我也尝试过没有它但无济于事。

服务

     public class FileService : IADReadWrite {
                private const int SIZE = 5;
                private const string COMPUTER_FILE = @"computers.txt";

                private List<Computer> computers = new List<Computer>();
                private readonly object @filelock = new object();

                private readonly Computer[] DEFAULT_COMPUTERS_LIST = new Computer[] {
                    new Computer(id:"W-CZC81371RS",Username:"A"),
                    new Computer(id:"W-CZC81371RQ",Username:"B"),
                };

                async Task<Computers> GetComputersAsymc() {
                    if (this.computers.Count == 0) {
                        var query = await Fetch();
                        this.computers = query.ToList();
                    }

                    var result = new Computers(this.computers);

                    return result;
                }

                public async Task<bool> AddComputerAsync(Computer computer) {

                    lock (filelock) {
                        if (this.computers.Any(x => x == computer)) {
                            return false;
                        }
                        this.computers.Add(computer);
                        File.WriteAllText(COMPUTER_FILE, JsonConvert.SerializeObject(this.computers, Formatting.Indented));
                        this.computers = JsonConvert.DeserializeObject<List<Computer>>(File.ReadAllText(COMPUTER_FILE));
                    }

                    return true;

                }

   ---------------------Helpers --------------------------
                private async Task<IEnumerable<Computer>> Fetch() {
                    if (!File.Exists(COMPUTER_FILE)) {
                        WriteComputersToDisk();
                    }
                    using (FileStream stream = new FileStream(COMPUTER_FILE, FileMode.Open, FileAccess.Read)) {
                        var raw = await File.ReadAllTextAsync(COMPUTER_FILE);
                        var comp = JsonConvert.DeserializeObject<List<Computer>>(raw);
                        return comp;
                    }

                }

               private void WriteComputersToDisk() {
                    var comps = DEFAULT_COMPUTERS_LIST;
                    var data = JsonConvert.SerializeObject(comps, Formatting.Indented);
                    File.WriteAllText(COMPUTER_FILE, data);
                }
        }

控制器

public class MyController:Controller
{ 
   MyController(IADReadWrite service)
   {
       this.service=service;
   }

   IADReadWrite service;
   [HttpGet]
   public async Task<List<Computer>> GetAll()
   {
        return await service.GetComputersAsync();
   }
   [HttpPost]
   public async Task AddComputer(Computer computer)
   {
      await service.AddComputerAsync(computer);
   }
}

设想

Initial list : [0,1]
Client hits controller calling `AddComputer`  {2}
I check the file , list is now: [0,1,2]
Client hits controller calling `GetComputers` -> it returns [0,1]
I hit F5 on the browser -> GetComputers gets hit again -> it returns [0,1,2]

PS 我没有发布这个Computer类,因为在这种情况下它并不重要(它实现IEquateable以防你想知道当我使用==运算符时它是否失败。最后两种方法处理磁盘文件的初始化。

标签: asp.net-corecachingsynchronizationlocking

解决方案


推荐阅读