【问题标题】:Union type in DDD model and in the databaseDDD 模型和数据库中的联合类型
【发布时间】:2020-02-19 04:14:05
【问题描述】:

在 NBA 篮球比赛中,我想存储逐场比赛数据。一个游戏有它的StartTime、两个Teams 和播放列表。每个播放都有其发生的时间和(取决于播放)不同的属性。有8种不同的打法,例如:“Rebound”、“FieldGoalAttempt”:

反弹:

  • 团队
  • 播放器
  • reboundType

射门尝试:

  • 团队

  • 射击游戏

  • 协助玩家

  • 阻塞播放器

  • shotType

  • 距离英尺

  • 积分

  • 位置

  • 结果

如你所见,这两种是完全不同的玩法——而且还有 6 种类型。这让我想到了我的第一个问题。

问题 1:如何在 C# 中实现它?

我的想法是创建一个类型Play,然后是8个类代表游戏类型,比如ReboundFieldGoalAttemptJumpBall这样的:

public class Play
{
    public int PlayId { get; set; }
    public int GameId { get; set; }
    public int PlayerId { get; set; }

    public Rebound Rebound { get; set; }
    public FieldGoalAttempt FieldGoalAttempt { get; set; }
    public Turnover Turnover { get; set; }
    public Foul Foul { get; set; }
    ...
    public JumpBall JumpBall { get; set; }

    public Game Game { get; set; }
    public Player Player { get; set; }
} 

但我不确定这是否是“代码异味”。我还有一些想法:objects 的列表?还是自定义构建的 C# 类,其行为类似于“Union”?所以第一个问题是我应该如何在 C# 中处理这种情况?我的第一个想法好吗?

问题2:毕竟,我想将这些剧本存储在数据库中。在我的架构中,我使用表示数据库中表的模型。对于我的逻辑,我创建了Service,所以模型是“贫血”的,有些人称之为“反模式”,但我不想谈论它。我的逻辑有服务,它对我有用。

如果我决定创建 Union 类 - 我如何将这些剧本存储在数据库中?

【问题讨论】:

  • 不清楚你在问什么,虽然你的问题描述性很强,但似乎与DDD关系不大,很难知道这些嵌套类型是什么(它们是什么类型的数据)
  • @MichaelRandall 等一下,让我澄清一下
  • 喜欢C++ union 或TypeScript union 类型? C# 没有类似的东西。
  • 您可以使用 F# 为您的域模型建模,然后从您的应用程序代码中引用您的域库。在 C# 中,它们将是子类型。如果您将域模型用作 ORM 实体,则可以专注于最佳域模型或最佳表模型。如果您同时获得两者,那只是领域的巧合。
  • 但我不确定这是否是“代码异味” - 如果您不确定,那么应该没问题。当您真正识别出一些可能会在进一步开发过程中带来问题的代码时,您会注意到“代码气味”。继续你的设计,当你真正开始遇到问题时 - 修复它。

标签: c# .net-core entity-framework-core domain-driven-design ef-core-3.1


【解决方案1】:

您可以为此使用继承。喜欢:

public class BasePlay
{
    public DateTimeOffset StartTime { get; set; }
    public Team TeamA { get; set; }
    public Team TeamB { get; set; }
}

public class JumpBallPlay : BasePlay
{
    public string ExtraProperty1 { get; set; }
}

public class FieldGoalAttemptPlay : BasePlay
{
    public string ExtraProperty2 { get; set; }
}

然后,您可以使用 Table Inheritance 将这些类与 EntityFramework 映射:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<BasePlay>()
        .HasDiscriminator<string>("PlayType")
        .HasValue<JumpBallPlay>("jumpBall")
        .HasValue<FieldGoalAttemptPlay>("fieldGoalAttemptPlay");
}

您的所有对象都将存储在同一个表中,但映射到不同的列(BasePlay 中的所有列都有一些共同点,请参阅Shared columns 部分)。额外的列PlayType 将包含戏剧的类型。

【讨论】:

  • 您是否考虑过 9 张不同牌桌的想法(8 种牌桌用于 8 种不同类型的游戏和 1 张牌桌Play 带有公共栏 + 8 个 FK 栏带有导航到特定游戏类型的导航)?显然只有在 FK 上不会为空,其他的都会为空。你认为 1 张桌子(约 40 列)服务所有游戏类型更好吗?
  • 从 SQL Server 的角度来看,1 个表优于 9 个表。另外,有 8 个 FK 的桌子吓到我了:)
  • 我知道了。我唯一担心的是“一张桌子”可以(从数据库的角度来看)与“assistingPlayer”一起玩“跳球”并说“result=2points”——这没有意义——但是数据库允许它。我应该担心这个吗?
  • 您是否担心如果一行将包含具体类型中不存在的属性值会发生什么? EF 将忽略所有其他列,除了那些映射到鉴别器列定义的类型的列。
  • 数据库大小如何?很多列都会为空
猜你喜欢
  • 1970-01-01
  • 2014-04-17
  • 2019-04-21
  • 2019-11-14
  • 2016-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多