6

业务

我有一个支付系统,可以通过 GiftCoupon、ClubMembershipCard 等进行支付。一个支付本身可以有多个支付组件

我有一个付款课程。它具有GiftCouponPayment、ClubMembershipCardPayment、CashPayment等支付组件。每个组件类型都满足一个公共接口 IPaymentComponent。我已经使用有关现有类型的知识来实现​​它。

问题

1)如何以抽象的方式实现这个功能——不知道所有存在的类型是什么?这意味着它需要适用于所有实现 IPaymentComponent 接口的类型。

2)如果无法在LINQ to SQL中实现,是否可以在实体框架中实现?

3) LINQ to SQL在 Payment 对象中生成 GiftCouponPayment 实体时是关联/聚合还是组合?

注意:我使用 LINQ to SQL 作为 ORM。GiftCouponPayment 和 Payment 是自动生成的类,这些对象由 ORM 创建。我通过使用部分类为这些类添加了更多功能。

注意:在数据库中,每个 PaymentComponent(例如 GiftCouponPayment)都有自己的属性(例如 CouponValue、CardValue 等)。因此Table-Per-Hierarchy 不会很好。我们需要单独的表格。该行有解决方案吗?

注意:在此付款之前,GiftCouponPayment 已存在于数据库中。我们需要使用客户提供的 GiftCouponPaymentID 来识别 GiftCouponPayment 对象。我们只需要更新此表中的 PaymentID 列。

泄漏抽象是指任何已实现的抽象,旨在降低(或隐藏)复杂性,其中底层细节并未完全隐藏

LINQ to SQL 图

在此处输入图像描述

参考

  1. 实体框架 4,继承与扩展?
  2. 如何选择继承策略http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx
  3. Fluent API 示例 - http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx

C# 代码

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;


    }
}
4

4 回答 4

1

您可以尝试使用 T 类型的通用抽象层或数据访问层。或者至少使方法通用。

于 2012-07-13T11:59:03.400 回答
1

我想你可能想暂时退出设计。我听到的是这样的:

支付由一个或多个组件组成,每个组件可以是多种类型中的一种

听起来你需要的是一个Payment表,然后是一个PaymentComponent与表有外键关系的Payment表。PaymentComponent然后,您可以在表上为您的各种付款方式实现继承。

于 2012-07-13T14:02:46.557 回答
1

您在这里基本上有一些问题:

  1. 如何对支付类型进行建模

    假设我们想要采用经典的 OOP 方式:

    您需要一个抽象的基类 Payment(或 PaymentBase)以及从它继承的各种类,例如 PaymentInCash、PaymentWithCreditCard 等。

    另一种方法是将 PaymentDetails 添加到 Payment 并创建 PaymentDetails 的层次结构,如果您选择这样做,请在以下所有点中将 Payment 替换为 PaymentDetails。

    对于使用多种方法的付款,您可以:

    一种。
    在 Payment或
    b下有一个 PaymentDetails 集合。创建一个名为 AggregatePayment 的类型,其中包含付款列表。

  2. 如何将付款类型映射到表格

    TPT 和 TPH 在这里都有效...

    对于 TPT,使用一张表进行付款,一张表用于每种付款。
    所有继承类型的表 PK 应该是基类型表的 FK。
    如果您有多个层次结构,则可以在第二(或任何其他)级别上使用 TPT 或 TPH(如果您使用的是 EF)。

    对于 TPH,使用一个带有鉴别列(例如 PaymentType)的表,并将未在层次结构中的所有实体之间共享的每一列标记为可为空。不要将同一列用于不同实体中的不同属性。在 EF 中,将每个实体映射到同一个表,条件为 PaymentType = (number goes here) 和 (column name(s) that should not be null) is not null。

    我的建议是,如果您有许多窄类型(每个属性很少),请使用 TPH,如果您有一些宽类型,请使用 TPT。

  3. 支付算法使用哪种设计模式/代码技术

    您在这里有更多选择:

    一种。使用部分类并在基类上放置一个抽象的 ProcessPayment() 方法并在继承类中覆盖。

    湾。使用基本的 PaymentProcessor 类和每个支付类型的特定 PaymentProcessor,例如 PaymentInCashProcessor。在此方法中,您可以使用反射来加载正确的 PaymentProcessor 类型,方法是存储字典或更好,使用泛型:

abstract class PaymentProcessor
{
}

abstract class PaymentProcessor<TPayment> : PaymentProcessor
    where TPayment : class, Payment
{
}

class PaymentInCashProcessor : PaymentProcessor<PaymentInCash>
{
}

// Use reflection to find types that inherits from PaymentProcessor<PaymentInCash>
// create an instance of the type you found
// then cast the instance to PaymentProcessor<PaymentInCash> to use

于 2012-07-13T16:26:45.900 回答
0

如果您设计 EF 模型,则可以在名为 payment 的基类上使用抽象属性。并让继承该类的所有付款类型:

实体框架模型

付款将具有所有共同属性,并且每种特定类型都可以具有自己的属性。

如果你有这种模型,你可以只查询付款。

这将返回所有继承支付类型的对象:


var allPayments = objectContext.Payments;
于 2012-07-13T13:38:59.550 回答