一般ORM设计问题

时间:2010-05-05 03:49:45

标签: database orm synchronization domain-driven-design

假设您有2个类,Person和Rabbit。一个人可以为兔子做很多事情,他/她可以喂它,买它并成为它的主人,或者放弃它。一只兔子一次可以没有或最多只有1个主人。如果它暂时没有喂食,它可能会死亡。

Class Person    
{    
    Void Feed(Rabbit r);    
    Void Buy(Rabbit r);
    Void Giveaway(Person p, Rabbit r);     

    Rabbit[] rabbits;    
}

Class Rabbit
{
   Bool IsAlive();    
   Person pwner;
}

域模型中有一些观察结果:

  1. 人和兔子可以互相引用
  2. 对一个对象的任何操作也可以更改另一个对象的状态
  3. 即使没有调用任何显式动作,对象中的状态仍然会发生变化(例如,Rabbit可能会被饿死,导致它从Person.rabbits数组中删除)
  4. 就DDD而言,我认为正确的方法是同步所有可能改变域模型中状态的调用。例如,如果一个人购买了一只兔子,他/她将需要在Person中获取一个锁以对兔子阵列进行更改,并且还需要在Rabbit中另一个锁定以在释放第一个之前更改其所有者。这可以防止2人声称是小兔子的拥有者的竞争条件。

    另一种方法是让数据库处理所有这些同步。谁使第一次调用获胜,但是数据库需要具有某种业务逻辑以确定它是否是有效的事务(例如,如果Rabbit已经拥有所有者,除非Person将其删除,否则它不能更改其所有者)

    两种方法都有优点/缺点,我希望“最佳”解决方案介于两者之间。你会如何在现实生活中做到这一点?你的经历和经历是什么?

    此外,域模型是否已提交其更改但在数据库中完全提交之前可能存在另一种竞争条件,这是否是一个有效的问题?

    对于第3次观察(即由于时间因素引起的状态变化)。你会怎么做?

2 个答案:

答案 0 :(得分:1)

这里有几个需要考虑的问题,可以帮助你进行设计:

  • 实际上,兔子需要知道它的主人是谁吗?意思是,它需要参考吗?如果您正在尝试对域进行建模,那么兔子可能不太可能知道它的所有者是谁(以及如果两个人共享该怎么办?)
  • 一个人应该直接提到兔子吗?或者你认为拥有一个更通用的界面更有意义,比如动物?这些操作似乎不是针对兔子的吗?
  • 关于线程和同步,您的应用程序是多线程的吗?您的应用中是否有可能让两个人同时成为兔子的主人?例如,如果您正在为宠物商店建模,那么就不可能发生这种情况(如果兔子没有对其所有者的引用,则此问题可能不再存在)。
  • 如果两个对象确实需要相互引用,我可能会在对象级别(带锁)进行同步。由于您可以在内存中更新域模型,然后将其保存到数据库(可能在应用程序关闭或者是桌面应用程序时),您总是希望内存处于一致状态。
  • 通常,根据需要从最简单的解决方案和重构开始。鉴于您的问题以及您在开发中的位置,我发现在对象级别或数据库中同步的差异可能不太可能是性能问题。

答案 1 :(得分:1)

1,兔子知道它的拥有者可能会或者可能不实用,在某些情况下,动物通过标签或微芯片知道它们的所有者....在DDD中,你建模在特定领域的背景下有意义的东西。但是他们可以互相了解。您将需要锁定以转移所有权。这对于大多数ORM而言相对简单

第三。当然老板拥有一只死兔子?但它足以作为杀死兔子的一部分,你将它从它的主人身上移除。至于什么杀死兔子,也许你需要课程GrimReaper及时安排查看所有ILivingThings,如果生命条件得到维持,如果不是ILivingThing.Slaughter()。Reap();