使实体类关闭以进行更改

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

付款包括现金付款和礼品券付款。 假设购买总额为550.可以按以下组件支付

1 Gift Coupon Valued 300 1 Gift Coupon Valued 200 I Cash Currency Valued 50 

在此处输入图像描述

我正在使用ORM的“InsertOnSubmit”function插入新的付款记录。 以下代码工作正常。 但是,如果我公司使用信用卡引入新的支付组件,我需要更改我的“付款”域类。 如何使支付类打开以进行扩展并关闭仍在使用ORM的 更改

注意:Payment类具有行为 (例如GetTotalAmountCollected)。 我正在努力使“付款”类满足OCP。

注意:优惠券类型有特定的行为 。 优惠券发行日期是否小于2000年1月1日,不应用于计算总金额(即,CouponValue应为零)。 请参阅使用策略模式重构代码 。

注意:我使用的是.Net 4.0

参考:

  1. 将ObjectContext.AddObject与Entity Framework一起使用时出错
  2. 使用策略模式重构代码
  3. 喜欢构成而不是inheritance?
  4. 代码优先与模型/数据库优先
  5. 使用Unity的策略模式和dependency injection
  6. 委托与OOP的C#策略设计模式
  7. 如何在C#中使用策略模式?
  8. EF代码优先inheritance:第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(); paymentEntity.CashPayments.Add(cashObj); paymentEntity.GiftCouponPayments = new System.Data.Linq.EntitySet(); 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().InsertOnSubmit(payment); } public void SubmitChanges() { MyDataContext.SubmitChanges(); } } 

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

我认为您可以对CashPayment类型进行部分类,该类型实现您自己的IPayment接口,可以在整个应用程序中使用。 这个界面也可以在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); } } 

也许一种替代方案是在ORM中利用inheritance。 因此,不是拥有N个集合,而是支付实体中的每个类型。 您将拥有同一集合中的所有子类型。 而所有这些,加起来将代表整个付款。

也许以不同的方式命名事物会更容易。 例如,让我们考虑购买的概念。 购买应该有一系列付款付款可以是一个抽象类, CashCouponCreditCard都可以从中inheritance。

以这种方式设置模型可以为您解决某些问题提供很多可能性。 您可以将所有付款视为相同并忘记不同的集合,并通过多态和双重调度进行大量控制。

这样,如果出现新的付款类型,您的模型将保持不变,您将只有一个新的子类型。

现在大多数ORM都支持不同的inheritance持久性方案,这有助于保持数据结构的清洁。

为每种付款类型创建新类型的附加值是什么? 我可以看到“通过金钱付款”和“通过凭证付款”之间的区别。 我同意有两种不同的类型来区分。

但是,为什么要区分CashPaymentCreditCardPayment等……? 您是否需要根据付款方式存储额外信息? 这种行为会改变吗?

为什么不保持简单,并为常规的“ Payment ”类型添加额外的属性,该类型充当鉴别器并向您提供付款的信息(通过信用卡,现金,……)?

 public class Payment {} public class VoucherPayment : Payment {} public class MoneyPayment : Payment { public PaymentMode { get; set; } } public enum PaymentMode { Cash, CreditCard } 

您可以使用每个层次表(http://msdn.microsoft.com/en-us/library/bb738443)定义模型,该表使用鉴别器(即您的案例中的PaymentType)列来指定特定的味道。你正在付款。 如果新的付款方式需要更多数据,那么您将会感到满意。 但是,EF在定义实体的方式以及这些实体如何映射到数据存储方面相当灵活。 您可能有一组常见的列,如Number和Value,然后全部共享,并将具有generics名称(如StringValue1)的列添加到数据库中。 然后,您可以将这些列映射到概念模型中更好的命名属性,这对您的域更有意义。

这基本上将您的数据库模式展平为单个表,但您的模型仍然是单独的类。 您可以将您的Payment类子类化为其他付款类型,而不会影响数据存储或Payment类; 但是,您需要修改模型以添加新的付款类型并将其映射到相应的列。