如何处理大量与我的应用程序无关的不变的支持数据

How to handle lots of unchanging backing data that is kind of unrelated to my application

背景

我正在创建一个分层的 .net 核心应用程序来处理棋盘游戏的跟踪活动。因此有很多数据来自游戏本身,例如:

该应用程序不处理此数据。此数据通常印在棋盘游戏随附的卡片上,因此不会更改。它可能有的唯一变化是当我手动添加新角色或由于发布新扩展而发生的事情时。

就应用程序而言,这些类似于您查找 table 美国各州的方式。该应用程序需要列出它们,以便您可以 select 它们,域中的实体持有对它们的引用,但它们的实际数据与应用程序本身无关。这只是查找数据。

除了这些数据很多而且其中一些是相关的。例如 objective 属于特定任务,奖励属于特定 objective.

问题

如果我的应用程序被设计为管理这些数据,那就没有问题了。然而,这种情况并非如此。它旨在管理 "Campaigns",即 2-5 名玩家坐下来使用这些卡片玩游戏。它正在管理 "instances" 具有附加属性的数据。

例如,创建了一个新的广告系列,并向该广告系列添加了一行 table。现在必须给它添加一个任务。

我不能只添加对任务数据的引用,因为我还需要存储特定于此活动的任务结果。因此,我创建了一个 CampaignMission 实体,它引用任务数据、活动 ID,并有一列用于任务结果。

但是那个任务数据有相关的 Objective 数据。数据只包含 objective 名称、描述、奖励等内容,但在活动中我还需要存储此活动任务特定的 objective 结果。因此,我再次创建一个 CampaignObjective,它引用 Objective 数据、CampaignMission,并且有一列用于 objective 结果。

在你知道之前,我正在为所有事情做这件事。 CampaignCharacter、CampaignWeapon、CampaignReward。我觉得我只是在复制游戏数据的结构,包括关系。

在游戏数据有关系的地方,我的战役实体感觉它们正在将这些关系镜像到这样的程度,从同一个对象,您可以通过两条不同的路径访问同一个游戏数据,原始路径游戏数据关系或活动实体 "replica" 关系。

例如,如果我想要第一个战役任务中第一个 objective 的第一个奖励的名称,您可以通过两种方式获取它:

Campaign.CampaignMissions[0].Mission.Objectives[0].Rewards[0].Name
Campaign.CampaignMissions[0].CampaignObjectives[0].CampaignRewards[0].Reward.Name

这两个都指向同一条游戏数据。我真的觉得应该只有一条路:

Campaign.Missions[0].Objectives[0].Rewards[0].Name

我被困在哪里

我不确定这是否正常,但总感觉不对。几乎就好像游戏数据甚至不应该成为应用程序的一部分一样。我的意思是游戏数据可以托管在某个第 3 方 API 上,这对我的实际应用程序没有任何影响。这只是我需要阅读的数据,但我觉得它正在以不应该的方式影响我的应用程序结构。

我的应用程序真的不需要知道任务游戏数据和战役中的任务之间的区别。它需要关心的只是一个活动可以有任务,而这些任务有一个名字等和一个结果。感觉 Mission 游戏数据本身不需要是我域中的实体。

我试过的

我尝试在我的域中保留单个实体,并在我的数据库中将它们分开。因此,例如域中的任务将包括游戏数据字段,如任务名称、任务结果和域列表 Objectives。

当从数据层请求战役的域任务时,将从 CampaignMission table 检索条目,连同来自任务 table 的游戏数据,然后通过 AutoMapper 展平并作为包含所有内容的单个任务实体返回域。

这给 Entity Framework 带来了一点噩梦,并在数据层和域之间来回处理映射,因为数据库中的 CampaignMission 也有 CampaignObjectives 链接到 Objectives 也必须被展平等等,我必须在我的域中跟踪所有这些的主键,这样当我想保留一些东西时,所有的东西都可以被展平并再次映射回来。就跟踪主要 keys/identity 而言,单个域实体由多个 table 中的条目表示是没有意义的。

我现在在考虑什么

我正在考虑将所有游戏数据移动到一个完全独立的项目中,与我的应用程序完全无关。然后我的应用程序可以查询项目,就好像它是某个第三方 API 或其他东西一样,并获取它需要的任何数据,我可以将它们全部排除在我的解决方案之外。

由于游戏数据在我的应用程序中不再有 ID,当我向活动添加任务时,它只会有一个 "name" 列,其中包含任务名称。当我想使用该任务时,我会从数据库中获取它并将其映射到域实体,因此此时它包含特定于活动的数据,例如任务结果以及名称。然后我会使用任务名称查询游戏数据项目,并将所有返回的数据也映射回实体,从而得到一个完整的实体。

这实质上是在复制我已经尝试过的行为,但无需通过简单地使用我可以查询的名称来跟踪游戏数据的身份。它从我的域中删除了支持游戏数据的概念,只剩下一个实体,Mission。

问题

到目前为止,我已经在这上面浪费了很多时间,我相信这一定是类似应用程序中的常见问题。在我继续尝试完全分离数据之前,我想知道是否有人有更好的解决方案来处理这种情况。

我不得不承认,输入 "What I'm Now Considering" 部分已经为我自己澄清了一些事情,但我仍然很想听听是否有更好的方法。

如果有人阅读了所有这些内容,请提前致谢。

这是您应该做的。首先,将游戏数据实体添加到 DbContext 作为 DbQuery<T>:

public DbQuery<Campaign> Campaigns { get; set; }

这将允许您查询它,但不允许更改。然后,由于游戏数据是静态的,您可能只想将其持久保存在一个单例中,然后您可以将其注入到您需要的地方。

无论哪种情况,在持久化的实际活动数据上,您应该只存储游戏数据概念的 ID。例如,MissionId,而不是 CampaginMission.Mission。当您需要实际的 Mission 信息时,只需根据 MissionId 直接从您的上下文中的 DbQuery<Mission> 属性 或您的单例 class 中查找.