代码之家  ›  专栏  ›  技术社区  ›  Community wiki

获取对象内部的所有关联/复合对象(以抽象方式)

  •  6
  • Community wiki  · 技术社区  · 2 年前

    商业 :

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

    :

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

    问题

    1) 如何在 摘要 在不知道存在的所有类型的情况下?这意味着它需要适用于所有实现IPaymentComponent接口的类型。

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

    3) 当 解决并发冲突 在Payment对象内生成GiftCouponPayment实体?

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

    注意:在数据库中,每个PaymentComponent(例如GiftCouponPayment)都有自己的属性(例如CouponValue、CardValue等)。因此 每个层次结构的表将不好 .我们需要分开的桌子。这方面有解决方案吗?

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

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

    LINQ到SQL关系图

    enter image description here

    参考 :

    1. Entity Framework 4, inheriting vs extending?
    2. 如何选择继承策略 http://blogs.msdn.com/b/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx
    3. 流利的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 回复  |  直到 8 年前
        1
  •  1
  •   Adam Robinson    13 年前

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

    付款由一个或多个组成部分组成,每个组成部分可以是多种类型中的一种

    听起来你需要的是 Payment 桌子,然后是 PaymentComponent 具有外键关系的表返回 付款 桌子然后,您可以在 付款部分 您的各种付款方式的表格。

        2
  •  1
  •   Freeman    13 年前

    您可以尝试使用一个抽象层或数据访问层,它将是T类型的泛型。或者至少使方法具有泛型。

        3
  •  1
  •   Danny Varod    13 年前

    这里基本上有几个问题:

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

      让我们假设我们想用经典的OOP方法来处理这个问题:

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

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

      用于多种方式的付款 ,您可以:

      a.在付款项下收集付款详细信息

      b.创建一个名为AggregatePayment的类型,该类型具有付款列表。

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

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

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

      对于TPH 使用一个带有鉴别器列(例如PaymentType)的表,并将层次结构中所有实体之间未共享的每一列标记为可为null。不要将同一列用于不同实体中的不同特性。在EF中,将每个实体映射到同一个表,条件为PaymentType=(此处为数字)和(不应为null的列名)不为null。

      我的建议是,如果你有很多窄类型(每个都有几个属性),那么就用TPH,如果你只有几个宽类型,那么就使用TPT。

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

      您在这里有更多选择:

      a.使用分部类,在基类上放一个抽象的ProcessPayment()方法,并在继承类中重写。

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

    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
    

        4
  •  0
  •   Preben Huybrechts    13 年前

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

    Entity Framework model

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

    如果你有这种类型的模型,你可以直接查询付款。

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

    
    var allPayments = objectContext.Payments;