동일한 엔티티를 다른 테이블에 맵핑


9

약간의 도메인 지식

상품을 지불하거나 환불 할 수있는 POS (Point Of Sales) 소프트웨어를 작성 중입니다. 지불 또는 환불시 현금, EFT (~ = 신용 카드), 포인트 카드, 바우처 등 사용할 송금 수단 을 지정해야합니다 .

이러한 자금 이체 수단은 유한하고 알려진 가치의 집합입니다 (일종의 열거 형).

까다로운 부분은 POS 단말기에서 지불 및 환불 (두 세트가 다를 수 있음)을 위해 이러한 수단의 사용자 정의 하위 집합을 저장할 수 있어야한다는 것입니다.

예를 들면 다음과 같습니다.

  • 사용 가능한 결제 수단 : 현금, EFT, 로열티 카드, 바우처
  • 사용 가능한 환불 수단 : 현금, 바우처

현재 구현 상태

다음과 같이 송금 수단의 개념을 구현하기로 선택합니다.

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...
}

"일반 열거 형"이 아닌 이유는 이러한 클래스 내부에 일부 동작이 있기 때문입니다. 또한 FluentNHibernate 매핑에서 참조하기 위해 내부 클래스를 private 대신 public으로 선언해야했습니다 (아래 참조).

사용 방법

지불 및 환불 수단은 항상 세트로 DB에 저장되거나 DB에서 검색됩니다. 두 세트 내부의 일부 값이 동일하더라도 실제로는 두 개의 고유 세트입니다.

사용 사례 1 : 새로운 결제 / 환불 수단을 정의

  • 기존 결제 / 환불 수단을 모두 삭제
  • 새로운 것을 삽입하십시오

사용 사례 2 : 모든 지불 / 환불 수단 검색

  • 저장된 모든 지불 / 환불 수단의 모음을 가져옵니다.

문제

지속성 측면에서 현재 디자인을 고수하고 있습니다. NHibernate (클래스 맵을 선언하기 위해 FluentNHibernate와 함께)를 사용하고 있으며 유효한 DB 스키마에 매핑하는 방법을 찾을 수 없습니다.

entity-name을 사용하여 클래스를 여러 번 맵핑 할 수 있지만 서브 클래스에서 가능하다는 것을 확신하지 못합니다.

내가 준비하지 않은 것은 MoneyTransferMean 공용 API를 변경하여 유지할 수 있도록하는 것입니다 (예 : bool isRefund둘을 구별 하기 위해 a 추가 ). 그러나 개인 차별 자 필드를 추가하는 것은 좋습니다.

내 현재 매핑 :

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...

이 매핑은 컴파일되지만 하나의 테이블 만 생성 하므로이 테이블을 쿼리 할 때 지불 / 환불을 구별 할 수 없습니다.

MoneyTransferMean다른 테이블과 엔티티 이름을 모두 참조하는 두 개의 매핑을 선언하려고했지만 예외가 발생 Duplicate class/entity mapping MoneyTransferMean+CashMoneyTransferMean합니다.

또한 서브 클래스 매핑을 복제하려고했지만 위와 동일한 예외로 이어지는 "부모 매핑"을 지정할 수 없습니다.

질문

현재 도메인 엔터티를 유지하는 솔루션이 있습니까?

그렇지 않은 경우 NHibnernate로 지속 가능하게 만들기 위해 엔티티에서 수행해야하는 가장 작은 리 팩터는 무엇입니까?


1
What I'm not ready to do is to alter the MoneyTransferMean public API to be able to persist it (for example adding a bool isRefund to differentiate between the two).왜 안돼? 문제를 해결하는 것은 간단하고 달콤한 변화입니다. (이 또한 중복 레코드 또는 함께 할 것입니다하지만 당신은 세 가지 값으로 만들 수 Flag타입) : Payment, Refund, Both. 두 가지 가치가 당신에게 도움이된다면, bool재산은 위대합니다.
Joshi

1
왜 결제 수단을 데이터베이스에 저장 하시겠습니까? 이름을 제외하고는 어떤 상태입니까?
berhalak

@AmitJoshi 이러한 작은 변경으로 인해 표면적으로 문제가 해결 될 수 있지만 비즈니스와 관련이없는 논리를 도메인에 추가하지 않으려 고합니다.
발견

@berhalak 실제로 데이터베이스에 저장하는 것은 약간 어색해 보입니다. 그러나 이것은 모든 상태가 데이터베이스에 있어야하는 프로젝트의 요구 사항입니다.
발견

답변:


0

모든 공통 속성 (필드)으로 하나의 단일 엔티티 MoneyTransferMean 을 작성 하고 MoneyTransferMean이 지불 또는 환불인지 또는 둘 다인지 판별하기 위해 두 개의 추가 필드 (부울)를 추가하지 않겠습니까? 그것을 유지하십시오.

또한 ID (PK)가있는 추가 엔티티로 수행 할 수 있으며 동일한 추가 필드를 추가하면 MoneyTransferMean과의 관계는 1 : 1이됩니다. 미운, 알아요,하지만 작동합니다.


도메인 프로젝트에 도메인과 관련이없는 복잡성을 추가하고 싶지 않습니다 (예 : 후속 if / else가 필요한 부울 추가). 또한이 클래스를 사용하는 사람들이 실수를하는 것을 원하지 않습니다 (부울을 확인하는 것을 잊고 각 값이 환불 수단이라는 것을 생각함으로써). 그것은 명백함에 관한 것입니다.
발견

0

두 번째로 @ DEVX75가 제안한 것에 추가하십시오. 트랜잭션 유형은 본질적으로 동일한 개념을 설명하지만 하나는 + ve이지만 다른 하나는 -ve입니다. 아마도 하나의 부울 필드를 추가하고 지불과 환불을 식별하기 위해 별도의 레코드가 있습니다.

UID가 있고 평균 레이블 이름을 ID로 사용하지 않는 경우 평균에 중복 이름을 허용하고 두 개의 현금 항목을 포함시킬 수 있습니다.

UID, 라벨, IsRefund

1, 현금, 거짓

2, 현금, 사실

3, 바우처, 거짓

4, 바우처, 사실

그러면 다음을 쉽게 얻을 수 있습니다.

거래 유형 = MoneyTransferMean.IsRefund? "환불": "지불"

거래 가치 = MoneyTransferMean.IsRefund? MoneyTransfer.amount * -1 : MoneyTransfer.amount

이렇게하면 거래에서 MoneyTransferMean.UID = 2를 참조한 경우 현금 환불 또는 현금 결제가 될 수있는 거래 유형이라는 것을 알기보다는 현금 환불이라는 것을 알 수 있습니다.


아 버거, 방금 공개 API를 편집하고 싶지 않다는 것을 알았습니다. 미안하지만 대답을 무시하십시오. 아마도 비슷한 문제 / 유스 케이스를 가진 사람들에게 유용 할 것이므로 그대로 두겠습니다.
FrugalTPH

0

마지막으로, 나는 내 개체를 복제하여 문제를 해결하기로 결정 MoneyTransferMean이 엔티티로 PaymentMeanRefundMean.

구현 방식은 비슷하지만 두 엔터티 간의 차이점은 비즈니스에서 의미가 있으며 가장 최악의 솔루션이었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.