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

时间:2012-07-13 11:56:32

标签: c# entity-framework oop linq-to-sql domain-driven-design

商家

我有一个支付系统,可以通过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等)。因此,每层次表层次不会很好。我们需要单独的表格。那条线上有解决方案吗?

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

  

漏洞抽象是指任何已实现的抽象,旨在减少(或隐藏)复杂性,其中底层细节未被完全隐藏

LINQ to SQL Diagram

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. Fluent API示例 - http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx
  4. 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;
    
    
        }
    }
    

4 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

我想你可能想暂时离开设计。我听到的是:

  

付款由一个或多个组件组成,每个组件可以是各种类型之一

你需要的是一个Payment表,然后是一个PaymentComponent表,其外键关系回到Payment表。然后,您可以在PaymentComponent表上实现继承,以用于各种付款方式。

答案 2 :(得分:1)

你基本上有一些问题:

  1. 如何为付款类型建模

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

    你需要一个基类,付款(或PaymentBase)是抽象的,并且需要从中继承的各种类,例如PaymentInCash,PaymentWithCreditCard等

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

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

    一个。在付款下有一系列PaymentDetails 或
    湾创建一个名为AggregatePayment的类型,其中包含付款清单。

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

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

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

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

    我的建议是,如果你有很多窄类型(每个属性很少),请选择TPH,如果你有几种宽类型,请选择TPT。

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

    您有更多选择:

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

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

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

    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

答案 3 :(得分:0)

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

Entity Framework model

付款将包含所有常见属性,并且每种特定类型都可以拥有自己的属性。

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

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


var allPayments = objectContext.Payments;