实体框架核心将实体存储在数据库上下文之外的内存中

时间:2019-04-25 06:04:26

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

我正在使用dotnet core 2.2控制台应用程序创建游戏服务器,我对实体框架在某些环境下的工作方式有一些误解。我想将用户信息存储在内存中,但要牢记两个重要因素。

  1. 我希望数据一直保持最新状态
  2. 我想对数据库进行最少的查询

这是我目前的操作方式:

DatabaseManager.cs

internal static class DatabaseManager
{
    public static async Task<User> FindUser(int userId, string token)
    {
        using (var dbContext = new musicContext())
        {
            return await dbContext.User.FirstOrDefaultAsync(u =>
                u.UserId == userId && string.Equals(u.Token, token, StringComparison.InvariantCulture));
        }
    }

    public static IEnumerable<Game> GetUserGames(User user)
    {
        using (var dbContext = new musicContext())
        {
            return dbContext.Game
                .Include(g => g.ParticipantOneNavigation)
                .Include(g => g.ParticipantTwoNavigation)
                .Where(g =>
                    g.ParticipantOneNavigation == user || g.ParticipantTwoNavigation == user);
        }
    }
}

Player.cs

internal class Player : IEquatable<Player>
{
    private readonly NetPeer _netPeer;
    private User _user;
    private int _userId;
    private string _token;

    public Player(NetPeer netPeer)
    {
        _netPeer = netPeer;
    }

    public async Task<bool> Authenticate(int userId, string token)
    {
        _user = await DatabaseManager.FindUser(userId, token);

        if (_user is null)
            return false;

        _userId = userId;
        _token = token;

        return true;
    }

    public NetPeer GetPeer()
    {
        return _netPeer;
    }

    public int GetPlayerId()
    {
        FlushData();

        return _user.UserId;
    }

    public string GetUsername()
    {
        FlushData();

        return _user.Username;
    }

    public string GetNickname()
    {
        FlushData();

        return _user.Nickname;
    }

    public string GetPhoneNumber()
    {
        FlushData();

        return _user.PhoneNumber;
    }

    public int GetCoins()
    {
        FlushData();

        return _user.Coins;
    }

    public int GetCups()
    {
        FlushData();

        return _user.Cups;
    }

    public bool IsAuthenticated()
    {
        return _user != null;
    }

    public bool IsSuspended(out DateTimeOffset suspendedUntil)
    {
        suspendedUntil = _user.SuspendedUntil.GetValueOrDefault();

        return _user.Suspended;
    }

    public bool Equals(Player other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return _playerId == other._playerId;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        return obj.GetType() == GetType() && Equals((Player)obj);
    }

    public override int GetHashCode()
    {
        return _playerId;
    }

    private async void FlushData()
    {
        _user = await DatabaseManager.FindUser(_userId, _token);
    }
}

这是一种最佳的做法吗?如果没有,您建议如何改善它?

1 个答案:

答案 0 :(得分:0)

您不能这样做,因为数据库是用于数据持久性的,并且不可避免地要进行频繁的查询才能使数据始终保持最新。

如果您需要实时信息交换工具,则需要开发和运行具有双工通信的服务器端应用程序(例如UDP,TCP,WebSocket。对于.NET Core,ASP.NET Core SignalR是建议)。它可以缓存,通知数据更新并将其推送到客户端。为了保留数据,您可以通过服务器端应用程序定期从缓存中更新数据库。这也可能有益于业务数据的完整性和安全性。