Aynı varlığı farklı tablolarla eşleme


9

Biraz alan bilgisi

Malları ödemeye veya geri ödemeye izin veren bir POS (Satış Noktası) yazılımı yazıyorum. Ödeme veya geri ödeme yaparken, hangi para transferinin kullanılacağını belirtmek gerekir : nakit, EFT (~ = kredi kartı), sadakat kartı, fiş vb.

Bu para transfer araçları sonlu ve bilinen bir değerler dizisidir (bir tür enum).

Zor kısmı, POS terminalinde hem ödemeler hem de geri ödemeler (iki set farklı olabilir) için bu araçların özel bir alt kümesini saklayabilmem gerektiğidir.

Örneğin:

  • Kullanılabilir ödeme anlamına gelir: Nakit, EFT, Sadakat kartı, Çek
  • Kullanılabilir geri ödeme şu anlama gelir: Nakit, Kupon

Mevcut uygulama durumu

Para transferi kavramını aşağıdaki gibi uygulamayı seçiyorum:

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

Bunun "düz enum" olmamasının nedeni, bu sınıfların içinde bazı davranışların olmasıdır. Ayrıca, FluentNHibernate eşlemesinde bunlara başvurmak için iç sınıfları (özel yerine) kamuya açıklamak zorunda kaldım (aşağıya bakın).

Nasıl kullanılır

Hem ödeme hem de geri ödeme araçları her zaman DB içinde / set olarak saklanır veya alınır. Her iki kümedeki bazı değerler aynı olsa da, bunlar gerçekten iki ayrı kümedir.

Kullanım örneği 1: yeni bir ödeme / geri ödeme aracı kümesi tanımlayın

  • Mevcut tüm ödeme / geri ödeme araçlarını silin
  • Yenilerini ekleyin

2. durum kullanın: tüm ödeme / geri ödeme araçlarını alın

  • Depolanan tüm ödeme / geri ödeme araçlarının koleksiyonunu alın

Sorun

Mevcut tasarımımla kalıcılık konusunda takılı kaldım. NHibernate (sınıf haritaları ilan etmek için FluentNHibernate ile) kullanıyorum ve bazı geçerli DB şemasına eşlemek için bir yol bulamıyorum.

Varlık adı kullanarak bir sınıfı birden çok kez eşleştirmek mümkün olduğunu ancak alt sınıflar ile mümkün olduğundan emin değilim bulundu.

Ne yapmaya hazır değilim, devam edebilmek için MoneyTransferMean genel API değiştirmek (örneğin bool isRefundikisi arasında ayrım yapmak için bir ekleme ). Ancak bazı özel ayırıcı alanı ya da benzeri eklemek tamam.

Mevcut eşlemem:

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

Bu eşleme yalnızca 1 tablo oluşturur ve bu tabloyu sorgularken ödeme / geri ödeme arasında ayrım yapamıyorum.

Hem MoneyTransferMeanfarklı tablo hem de varlık adı ile başvuran iki eşleme bildirmeye çalıştım, ancak bu beni bir istisna yol açar Duplicate class/entity mapping MoneyTransferMean+CashMoneyTransferMean.

Ayrıca alt sınıf eşleştirmelerini çoğaltmaya çalıştım ama beni yukarıdaki gibi aynı özel duruma götüren bir "üst eşleme" belirleyemiyorum.

Soru

Mevcut etki alanı varlıklarımı devam ettirmek için bir çözüm var mı?

Değilse, onları NHibnernate ile devam ettirmek için varlıklarımda gerçekleştirmem gereken en küçük refactor ne olurdu?


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).: Neden olmasın? Sorununuzu çözmesi basit ve tatlı bir değişikliktir. (İki de yinelenen kayıtları veya yapacak karşın üç olası değerleri ile telafi edebiliriz Flagtipi): Payment, Refund, Both. İki değer sizin için yaparsa, boolözellik harika.
Amit Joshi

1
Bu ödeme yöntemlerini neden veritabanında saklamak istiyorsunuz? Adından başka orada durum nedir?
berhalak

@AmitJoshi Böyle küçük bir değişiklik (yüzeyde) sorunu çözebilse de, alanımla işle ilgili olmayan bir mantık eklemekten kaçınmak istiyorum.
Benekli

@berhalak Gerçekten, bunları veritabanında saklamak biraz hantal görünüyor. Ancak bu projeden tüm devletin veritabanında olması şarttır.
Benekli

Yanıtlar:


0

Neden MoneyTransferMean'ın tüm ortak özellikleri (alanları) olan tek bir varlık oluşturmuyorsunuz ve MoneyTransferMean'ın Ödeme veya Geri Ödeme olup olmadığını veya her ikisini birden belirlemek için yalnızca 2 ek alan (boolean) eklemiyorsunuz ???? Kalsın ya da kalmasın.

Ayrıca Id ile ekstra bir Varlık (PK) ile yapılabilir, aynı ekstra alanları ekleyin, MoneyTransferMean ile ilişki 1: 1 olacaktır. Çirkin, biliyorum, ama işe yaramalı.


Etki alanı projemle ilgili olmayan karmaşıklık eklemek istemiyorum (bir sonraki if / else gerektiğinde boolean ekleme gibi). Ayrıca bu sınıfları kullanacak insanların hata yapmasını istemiyorum (boolean'ı kontrol etmeyi unutup her değerin örneğin geri ödeme anlamına geldiğini düşünerek). Her şey açıklıkla ilgili.
Benekli

0

İkincisi ve @ DEVX75'in önerdiği şeye ekliyorum, çünkü işlem türleriniz temel olarak aynı kavramı açıklıyor, ancak biri diğerinden + ve diğeri -ve. Muhtemelen sadece bir boole alanı eklerdim ve geri ödemeleri ödemelerden ayırt etmek için ayrı kayıtlara sahip olurum.

Bir UID'niz olduğunu ve araç etiketi adını kimlik olarak kullanmadığınızı varsayarsak, araçların yinelenen adlarına izin verebilir ve örneğin iki nakit girişi ekleyebilirsiniz:

UID, Etiket, Geri Ödeme

1, Nakit, yanlış

2, Nakit, gerçek

3, Çek, yanlış

4, Çeki, gerçek

Ardından aşağıdakileri kolayca alabilirsiniz:

İşlem Türü = MoneyTransferMean.IsRefund? "İade ödemesi"

İşlem Değeri = MoneyTransferMean.IsRefund? MoneyTransfer.amount * -1: MoneyTransfer.amount

Bu şekilde, işlemlerinizde MoneyTransferMean.UID = 2'ye başvurduysanız, bunun nakit iadesi veya nakit ödeme olabilen bir işlem türü olduğunu bilmek yerine bunun nakit iadesi olduğunu bilirsiniz.


Hata! Herkese açık API'yı düzenlemek istemediğinizi / düzenleyemeyeceğinizi belirttiniz. Cevabımı özür dilerim / görmezden gelirim, ama belki de benzer problem / kullanım durumu olan başkaları için yararlı olacaktır.
FrugalTPH

0

Sonuçta, benim varlık çoğaltarak sorunu çözmek için karar MoneyTransferMeaniki tarafa PaymentMeanve RefundMean.

Uygulamada benzer olmasına rağmen, iki kurum arasındaki ayrım işte mantıklı ve benim için en kötü çözümdü.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.