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