我目前正忙着在C#中试验一些东西,这样我就可以按照自己的喜好构建一个Web服务器了。 Web服务器将专门为我正在处理的项目而制作。希望它能比其他网络服务器运行得更好。
现在我一直在努力寻找一种有效的方法将数据库信息存储在应用程序的内存中。
到目前为止,我已经尝试过制作类似于带有它的字段的表格。为表中的每一行创建该类的新实例。然后创建类似于索引的某些Dictionary变量。就像一个用于Id,一个用于用户名。它工作正常,但与数据库中的表相比,它消耗的内存大约是内存的3倍。我做过的例子:
class User()
{
public int Id;
public string Name;
//other columns, the same way
}
至于字典:
Dictionary<int, User> UserIDIndex = new Dictionary<int, User>();
User NewUser = new User();
NewUser.Name = "Something...";
UserIDIndex.Add(someId, NewUser);
我也尝试过DataTable,但根本没有成功。它比类和字典方法消耗的内存至少多50%。
我很好奇是否还有其他任何方式,一种更有效的信息存储方式?
所有这些背后的原因:每秒都需要更新和选择大量数据。我担心直接从数据库中执行此操作太过分了。因此,首先(启动和某些条件)想要在内存中加载一些东西。然后,在某些点,更新内存中的值。然后,这么多秒,更新数据库中的这些值。我想这也可以用NodeJS完成,但是它使用了1个核心,我觉得有点难过。如果你遇到CPU问题,那不是未来的证明。
答案 0 :(得分:0)
从性能的角度来看,如果分组SQL请求的性能明显优于单个请求序列,那么您的方法可能会很好。
主要的不便之处在于崩溃时应用程序的稳健性。可能需要实施一些恢复机制。
关于存储器,通过观察可用的RAM来评估存储器需求是困难的,因为存储器不能立即释放:它在需要时在系统的需求下完成。
要计算实际使用的内存,请评估对象的大小并乘以计数。
处理用户输入时,您是否评估了平均计算时间 和没有数据库更新?
答案 1 :(得分:0)
我建议使用像Entity Framework Core(EF Core)中幕后使用的可观察集合。 (我没有看过引擎盖,我发现.local让我可以访问内存中的副本)
Public ObservableCollection<user> users = new ObservableCollection<user>();
由于使用EF Core在引擎盖下使用相同的结构,您可以编写允许您在使用它们之间轻松往返的内容。棘手的部分是以一种非常容易使用EF Core或InMemory实现的方式定义事物。以下示例基于使用EF Core。在下面的代码中,我创建了一个可以使用的公共基础。我包装了Ef Core使用的DbContext。包装器允许我访问驻留在实体框架中的本地内存数据。
现在数据在内存中,您只需将其保存到磁盘即可。由于您可以选择EF Core,因此可以轻松地为您的环境比较选项。为了快速测试,我序列化为文件。从同一个文件重新加载也很容易回到我保存的状态。
警告:我的包装器只是将整个数据库加载到内存中,因为它在我的情况下很小。 .ToList()是确保将数据加载到EF Core内存的代码。
查看此Entity Framework Core How To
的链接CODE:
using Blog.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace Blog
{
public interface IData_Common
{
ObservableCollection<User> Users { get; }
ObservableCollection<Other> Others { get; }
}
public interface IData_InMemoryContext : IData_Common
{
IData_InMemoryContext Create();
}
public class Data_InMemoryContext : IData_InMemoryContext
{
public ObservableCollection<User> Users { get; set; }
public ObservableCollection<Other> Others { get; set; }
public Data_InMemoryContext()
{
Users = new ObservableCollection<User>();
Others = new ObservableCollection<Other>();
}
public IData_InMemoryContext Create()
{
Users = new ObservableCollection<User>();
Others = new ObservableCollection<Other>();
return new Data_InMemoryContext();
}
}
public interface IData_Context
{
DbSet<User> Users { get; set; }
DbSet<Other> Others { get; set; }
IData_Context Create();
}
public class Data_Context : DbContext, IData_Context
{
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Other> Others { get; set; }
public IData_Context Create()
{
return new Data_Context();
}
public Data_Context()
{
//this.Configuration.LazyLoadingEnabled = false;
}
}
// I wrap context so that I can use the InMemoryContext interface
public class WrapData_Context : IData_InMemoryContext
{
private object _Context;
private DbSet<User> _Users;
private DbSet<Other> _Others;
public WrapData_Context(Data_Context DbContext)
{
if (DbContext is null)
{
throw new NullReferenceException("DbContext can't be null");
}
_Context = DbContext;
// Need to make sure the data is accessed so it is loaded to the local ObservableCollections
DbContext.Users.ToList();
_Users = DbContext.Users;
DbContext.Others.ToList();
_Others = DbContext.Others;
}
public IData_InMemoryContext Create()
{
var context = new Data_Context();
return new WrapData_Context(context);
}
// Properties
public ObservableCollection<User> Users => _Users.Local.ToObservableCollection();
public ObservableCollection<Other> Others => _Others.Local.ToObservableCollection();
}
}
样本用法:
Data_Context _c = new Data_Context();
WrapData_Context _context = new WrapData_Context(_c);