繁体   English   中英

将同一实体映射到不同的表

[英]Mapping the same entity to different tables

一点领域知识

我正在编写一个 POS(销售点)软件,它允许支付货物或退款。 在付款或退款时,需要指定使用哪种汇款方式:现金、EFT(~=信用卡)、会员卡、代金券等。

这些汇款方式是一组有限且已知的值(一种枚举)。

棘手的部分是我需要能够在 POS 终端上存储这些方式的自定义子集,用于付款和退款(两组可能不同)。

例如:

  • 可用的付款方式:现金、电子转帐、会员卡、代金券
  • 可用退款方式:现金、代金券

实施现状

我选择实现汇款方式的概念如下:

public abstract class MoneyTransferMean : AggregateRoot
{
    public static readonly MoneyTransferMean Cash = new CashMoneyTransferMean();
    public static readonly MoneyTransferMean EFT = new EFTMoneyTransferMean();
    // and so on...

    //abstract method

    public class CashMoneyTransferMean : MoneyTransferMean
    {
        //impl of abstract method
    }

    public class EFTMoneyTransferMean : MoneyTransferMean
    {
        //impl of abstract method
    }

    //and so on...
}

它不是“普通枚举”的原因是这些类内部存在一些行为。 我还必须将内部类声明为 public(而不是私有),以便在 FluentNHibernate 映射中引用它们(见下文)。

如何使用

支付和退款手段总是作为一个集合存储在/从数据库中检索。 它们实际上是两个不同的集合,即使两个集合中的某些值可能相同。

用例 1:定义一组新的支付/退款方式

  • 删除所有现有的支付/退款方式
  • 插入新的

用例2:检索所有支付/退款方式

  • 获取所有存储的付款/退款方式的集合

问题

我在持久性方面坚持我目前的设计。 我正在使用 NHibernate(使用 FluentNHibernate 来声明类映射),但找不到将其映射到某些有效数据库模式的方法。

我发现可以使用entity-name多次映射一个类,但是我不确定子类是否可行。

我还没有准备好改变 MoneyTransferMean 公共 API 以使其能够持久化(例如添加bool isRefund以区分两者)。 但是,添加一些私有鉴别器字段左右是可以的。

我目前的映射:

public sealed class MoneyTransferMeanMap : ClassMap<MoneyTransferMean>
{
    public MoneyTransferMeanMap()
    {
        Id(Entity.Expressions<MoneyTransferMean>.Id);
        DiscriminateSubClassesOnColumn("Type")
            .Not.Nullable();
    }
}

public sealed class CashMoneyTransferMeanMap : SubclassMap<MoneyTransferMean.CashMoneyTransferMean>
{
    public CashMoneyTransferMeanMap()
    {
        DiscriminatorValue("Cash");
    }
}

public sealed class EFTMoneyTransferMeanMap : SubclassMap<MoneyTransferMean.EFTMoneyTransferMean>
{
    public EFTMoneyTransferMeanMap()
    {
        DiscriminatorValue("EFT");
    }
}

//and so on...

这个映射编译但是它只生成 1 个表,在查询这个表时我无法区分付款/退款。

我试图声明两个映射,引用具有不同表和实体名称的MoneyTransferMean但这导致我出现异常Duplicate class/entity mapping MoneyTransferMean+CashMoneyTransferMean

我还尝试复制子类映射,但我无法指定“父映射”,这导致我遇到与上述相同的异常。

是否存在保留我当前域实体的解决方案?

如果不是,我需要对我的实体执行的最小重构是什么,以使它们与 NHibnernate 保持一致?

为什么不创建一个具有所有通用属性(字段)的单一实体MoneyTransferMean ,然后添加 2 个额外字段(布尔值)来确定 MoneyTransferMean 是 Payment 还是 Refund,还是两者兼而有之???? 坚持与否。

也可以使用带有 Id (PK) 的额外实体来完成,添加相同的额外字段,与 MoneyTransferMean 的关系将是 1:1。 丑陋,我知道,但它应该工作。

我想补充一下@DEVX75 的建议,因为您的交易类型基本上描述了相同的概念,尽管一个是 +ve 而另一个是 -ve。 不过,我可能只添加一个布尔字段,并有单独的记录来区分退款和付款。

假设您有一个 UID 并且没有使用手段标签名称作为 ID,您可以允许手段重复名称,并包括两个现金条目,例如:

UID、标签、IsRefund

1、现金、假

2、现金,真实

3、代金券,假的

4、代金券,真实

然后您可以轻松获得以下内容:

交易类型= MoneyTransferMean.IsRefund? “退款”:“付款”

交易价值= MoneyTransferMean.IsRefund? MoneyTransfer.amount * -1 : MoneyTransfer.amount

这样,如果您在交易中引用了 MoneyTransferMean.UID = 2,您就知道这是现金退款,而不是知道这是一种可以是现金退款或现金支付的交易类型。

最后,我决定通过将我的实体MoneyTransferMean复制到两个实体PaymentMeanRefundMean来解决这个问题。

虽然在实现上相似,但两个实体之间的区别在业务中是有意义的,对我来说是最不糟糕的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM