考虑使用台球应用程序。您可能需要的一种模型是Match
,它引用多个Game
对象,每个Game
对象包含该游戏的评分数据。当然,Match
和Game
都会引用Player
,因为您需要知道谁在玩。所以考虑到这个相对简单的模型:
class Match
{
Player Player1;
Player Player2;
List<Game> Games;
}
class Game
{
Player Player1;
Player Player2;
// ... scoring data
}
class Player
{
string PlayerName;
}
我们希望将匹配保存到某个存储(类型不重要,但是,例如,假设我们在Azure中存储了JSON序列化对象的blob)。
我们可以这样做的简单方法是:
storage.SaveBlob(JsonConvert.SerializeObject(myMatch));
但这会保存Player1
和Player2
的多个副本 - 一个用于匹配,一个用于比赛中的每个游戏。
我们可以将Game
更改为:
class Game
{
[JsonIgnore]
Player Player1;
[JsonIgnore]
Player Player2;
// ... scoring data
}
这解决了我们重复的播放器问题,但现在我们遇到的问题是,反序列化需要Match
来修复所有引用的Game
对象的数据成员,以及更多其他类似对象复杂的情况。
我们可以再次更新Game
:
class Game
{
[JsonIgnore]
Match Match;
[JsonIgnore]
Player Player1 => Match.Player1;
[JsonIgnore]
Player Player2 => Match.Player2;
// ... scoring data
}
这简化了问题,但仍需要Match
反序列化来修复其属性。此外,添加此类抽象会导致Game
对象必须的部分Match
的问题。从概念上讲情况并非如此(没有理由你没有Game
不是完整Match
的一部分),所以这似乎是一种糟糕的方法。
其他选项可能是将Match
更改为:
class Match
{
Player Player1 => Games.First().Player1;
Player Player2 => Games.First().Player2;
List<Game> Games;
}
这种解决了我们将Player
个对象保存为多个类的问题,但它会导致大量的数据重复。此外,如果我们将所有这些数据保存到存储中,然后Player
更改其评级级别,例如,我们通常希望更新所有引用(还有情况可能并非如此,但现在暂时忽略。)
目标是在保持一定量的数据规范化的同时进行干净的序列化/反序列化。那么......应该做些什么?这不是常见的问题吗?
答案 0 :(得分:-2)
对于关系数据库来说这是一个很好的工作。
将实体(匹配,游戏,玩家)存储在不同的表格中。
使用&#34; join&#34;检索它们操作
你提出的建议就是重新发明那种已经存在了几十年的轮子。
另一方面,看起来您正在存储不会发生变化的历史数据,因此非关系型数据库(NoSQL)可能适合您。存储非常便宜,所以不要在这里和那里担心一些重复的数据(因为它不会改变)。
注意:如果您的应用程序可能允许存储的数据发生更改,那么重复的数据就是 evil 并且应该不惜一切代价避免(因此没有人更新一个副本而不更新其他副本),使用关系那种情况下的模型。