制作实体类关闭的变化(Making Entity Class Closed for Changes)

2019-06-14 19:49发布

我有如下所示数据库的关系。 基于LINQ to SQL的ORM正在创建的域对象。

的支付包括现金支付和礼券付款的。 假设购买总额为550可以缴纳下列组件

1 Gift Coupon Valued 300

1 Gift Coupon Valued 200

I Cash Currency Valued 50

我将使用ORM的“InsertOnSubmit”功能的新的缴费记录。 下面的代码是工作的罚款。 但是,如果我公司使用的信用卡引入一个新的支付组件,我需要改变我的“支付”领域类。 我如何支付类对扩展开放和关闭的变化仍然使用ORM?

注:支付类有行为 (例如GetTotalAmountCollected)。 我试图使“支付”类,以满足OCP。

注:对于优惠券类型的特定行为 。 签发日期优惠券小于1/1/2000,它不应该在计算的总金额(即COUPONVALUE应该是零)使用。 请参阅使用策略模式重构的代码也。

注:我使用.NET 4.0

参考:

  1. 使用ObjectContext.AddObject与实体框架时,遇到了一个错误
  2. 使用策略模式重构代码
  3. 身高超过组成继承?
  4. 代码优先和模型/数据库一
  5. 策略模式和依赖注入使用Unity
  6. C#Strategy设计模式的代表VS OOP
  7. 如何使用C#的战略格局?
  8. 继承与EF代码第一:第2部分-每个类型表(TPT) http://weblogs.asp.net/manavi/archive/2010/12/28/inheritance-mapping-strategies-with-entity-framework-code-first -ctp5部分-2-表每类型tpt.aspx

C#代码:

public class PaymentAppService
{
    public RepositoryLayer.ILijosPaymentRepository Repository { get; set; }

    public void MakePayment()
    {
        DBML_Project.Payment paymentEntity = new DBML_Project.Payment();
        paymentEntity.PaymentID = 1;
        paymentEntity.PaymentType = "PurchaseP";

        DBML_Project.CashPayment cashObj = new DBML_Project.CashPayment();
        cashObj.CashPaymentID = 1;
        cashObj.CurrencyNumber = 123;
        cashObj.CurrencyValue = 100;

        DBML_Project.GiftCouponPayment giftCouponObj = new DBML_Project.GiftCouponPayment();
        giftCouponObj.GiftCouponPaymentID = 1;
        giftCouponObj.CouponValue = 200;
        giftCouponObj.CouponNumber = 124;

        paymentEntity.CashPayments = new System.Data.Linq.EntitySet<DBML_Project.CashPayment>();
        paymentEntity.CashPayments.Add(cashObj);

        paymentEntity.GiftCouponPayments = new System.Data.Linq.EntitySet<DBML_Project.GiftCouponPayment>();
        paymentEntity.GiftCouponPayments.Add(giftCouponObj);

        Repository.InsertEntity(paymentEntity);
        Repository.SubmitChanges();
    }
}

库:

public class LijosPaymentRepository : ILijosPaymentRepository
{
    public System.Data.Linq.DataContext MyDataContext { get; set; }

    public void InsertEntity(DBML_Project.Payment payment)
    {
        //Insert the entity
        MyDataContext.GetTable<DBML_Project.Payment>().InsertOnSubmit(payment);
    }

    public void SubmitChanges()
    {
        MyDataContext.SubmitChanges();
    }
}

Answer 1:

对于@Lijo试图解决抽象的方法会更好的问题

我认为你可以在实现自己的IPayment接口,可通过整个应用程序使用的CashPayment类型的分部类。 然后,这个接口还可以在类:CreditCardPayment:

例:



public interface IPayment
{
     int Id { get; set; }
     int PaymentId { get; set; }
     //Other payment specific properties or methods
}

public partial class CashPayment : IPayment
{
    public int Id 
    {
       get { return CashPaymentId ; }
       set { CashPaymentId = value; }
    }

    //Other properties

}

public partial class CreditCardPayment : IPayment 
{
   //more code ...
}

在你的EF方面有所收获的所有款项




public partial class PaymentEntities //The name of your EF entities
{
   public IQueryable AllPayments
   {
      return this.CashPayment.Union(this.CreditCardPayment); //This is not good, but just an example. The abstract class approach would be better here.
   }

    public void InsertPayment(IPayment payment)
    {
         this.AddObject(payment.GetType().Name, payment);
    }
}



Answer 2:

也许一个替代方案是采取继承的优势,在ORM为好。 以便代替具有N个集合,一个用于在付款实体每种类型的。 你会拥有所有的亚型的同一收藏。 而所有这些,加起来将代表整个付款。

也许它会更容易一点不同的事物命名。 例如,让我们考虑一个采购的概念。 选购时应有支付的集合。 和支付可能是一个抽象类,从现金优惠券信用卡式 ,全部继承。

具有模型中设置了这种方式打开的可能性关于如何可以解决某些问题很大。 你可以把所有款项一样,而忘记了明显的集合,加上通过多态性与有控制的大量的双重分派 。

这样,如果一个新的付款方式出现的时候,你的模型将保持不变,你会只是有一个新的亚型。

大多数奥姆斯现在支持继承不同的持久性方案,这将有助于保持你的数据结构干净为好。



Answer 3:

什么是创造各种付款方式的一种新型的增值? 我可以看到一个“用金钱支付”和“通过凭证进行付款”之间的区别。 我同意有两种不同的类型进行区分。

但是,为什么要作区分CashPayment ,一CreditCardPayment等..? 你有存储额外的信息取决于支付的类型? 是否改变行为?

为什么你不只是保持简单,和一个额外的属性添加到常规的“ Payment ”型,它作为鉴别,并为您的支付是如何制作的信息(通过的信用卡,现金,....)?

public class Payment {}

public class VoucherPayment : Payment {}

public class MoneyPayment : Payment
{
    public PaymentMode { get; set; }
}

public enum PaymentMode 
{
    Cash,
    CreditCard
}


Answer 4:

您可以定义使用表每层次(http://msdn.microsoft.com/en-us/library/bb738443),它采用鉴别模型(即PaymentType你的情况)列指定的特殊味道支付你在做。 然后,你会感激,如果需要更多数据的新的付款方式添加列; 然而,EF是你如何定义实体的术语以及这些实体映射到您的数据存储相当灵活。 你也许可以有一个共同的一套像宗数和金额列,然后全力以赴sharepointy与通用名称,如StringValue1到数据库中添加列。 然后,您可以在您的概念模型,将更有意义,您的域名映射这些列,以更好地命名属性。

这基本上拉平数据库架构成一个单一的表,但你的模型保持独立的类。 你也可以继承额外支付类型而不影响数据存储或支付类的支付类; 但是,您将需要修改模型,将它们添加新的付款方式,并映射到相应的列。



文章来源: Making Entity Class Closed for Changes