Business:
I have a payment system in which payment can be made though GiftCoupon, ClubMembershipCard etc. One payment itself can have multiple payment components
Class:
I have a Payment class. It has payment components like GiftCouponPayment, ClubMembershipCardPayment, CashPayment and so on. Each component type satisfy a common interface IPaymentComponent. I have implemented it using the knowledge about the existing types.
Questions
1) How to implement this function in a abstract way – without knowing what all are the types that exist? That means it need to work for all types that implement IPaymentComponent interface.
2) If it is not possible to achieve it in LINQ to SQL, is it possible in Entity Framework?
3) Is it association / aggregation or composition when LINQ to SQL generate GiftCouponPayment entities inside Payment object?
Note: I am using LINQ to SQL as ORM. GiftCouponPayment and Payment are autogenerated classes and these objects are created by ORM. I have added more functionality to these classes by using partial classes.
Note: In database each PaymentComponent (E.g. GiftCouponPayment) has its own properties (e.g CouponValue,CardValue etc). Hence Table-Per-Hierarchy will not be good. We need separate tables. Is there a solution in that line?
Note: GiftCouponPayment already exist in the database prior to this payment. We need to identify the GiftCouponPayment object by using GiftCouponPaymentID provided by the customer. We just need to update the PaymentID column in this table.
A leaky abstraction refers to any implemented abstraction, intended to reduce (or hide) complexity, where the underlying details are not completely hidden
LINQ to SQL Diagram
REFERENCE:
- Entity Framework 4, inheriting vs extending?
- How to choose an Inheritance Strategy http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx
- Fluent API Samples - http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx
C# CODE
public interface IPaymentComponent
{
int MyID { get; set; }
int MyValue { get; set; }
int GetEffectiveValue();
}
public partial class GiftCouponPayment : IPaymentComponent
{
public int MyID
{
get
{
return this.GiftCouponPaymentID;
}
set
{
this.GiftCouponPaymentID = value;
}
}
public int MyValue
{
get
{
return this.CouponValue;
}
set
{
this.CouponValue = value;
}
}
public int GetEffectiveValue()
{
if (this.CouponNumber < 2000)
{
return 0;
}
return this.CouponValue;
}
}
public partial class Payment
{
public List<IPaymentComponent> AllPaymentComponents()
{
List<IPaymentComponent> allPayComps = new List<IPaymentComponent>();
List<GiftCouponPayment> giftCouponPaymentList = new List<GiftCouponPayment>();
List<CashPayment> cashPaymentList = new List<CashPayment>();
foreach (GiftCouponPayment g in this.GiftCouponPayments)
{
giftCouponPaymentList.Add(g);
allPayComps.Add(g);
}
foreach (CashPayment c in this.CashPayments)
{
cashPaymentList.Add(c);
allPayComps.Add(c);
}
return allPayComps;
}
}
You can try to use an abstraction layer or a data acces layer that will be generic of type T. Or at least make the methods generic.
If you design your EF model you can use the abstract property on a base class called payment. And let inherit all your payment types that class:
Payment will have all common properties, and every specific type can have their own properties.
If you have this kind of model you can just query for payments.
This returns all objects that inherit of the payment type:
I think you might want to step back from the design for a moment. What I've heard is this:
What it sounds like you need is a
Payment
table, then aPaymentComponent
table with a foreign key relation back to thePayment
table. You can then implement inheritance on thePaymentComponent
table for your various forms of payment.You basically have a few of issues here:
How to model the payment types
Lets assume we want to go at this the classic OOP way:
You need a base class, Payment (or PaymentBase) which is abstract and various class which inherit from it e.g. PaymentInCash, PaymentWithCreditCard and etc.
An alternative could be adding PaymentDetails to Payment and creating a hierarchy of PaymentDetails, if you choose to do this, the replace Payment with PaymentDetails in all the following points.
For payments with multiple methods, you could either:
a. Have a collection of PaymentDetails under a Payment
or
b. Create a type called AggregatePayment which has a list of Payments.
How to map the payment types to tables
Both TPT and TPH are valid here...
For TPT use one table for Payment and one table for each kind of payment.
All the inheriting type's tables PK's should be an FK to the base type's table.
If you have multiple levels of hierarchy, you can use either TPT or TPH on the second (or any other) level if you are using EF.
For TPH use one table with a discriminator column (e.g. PaymentType), and mark each column that is not shared between all entities in the hierarchy as nullable. Do not use the same column for different properties in different entities. In EF, map each entity to the same table with the condition PaymentType = (number goes here) and (column name(s) that should not be null) is not null.
My recommendation is, if you have many narrow types (few properties each) go with TPH, if you have a few wide types go with TPT.
Which design pattern / code technique to use for payment algorithm
You have more options here:
a. Use partial classes and put an abstract ProcessPayment() method on the base class and override in the inheriting classes.
b. Use a base PaymentProcessor class and a specific PaymentProcessor per payment type e.g. PaymentInCashProcessor. In this method you can use reflection to load the correct PaymentProcessor type by either storing a dictionay or better yet, using generics: