Home > Software design >  Abstract Factory Mapping EF Core .NET 6
Abstract Factory Mapping EF Core .NET 6

Time:01-25

I have tremendous doubts.

I'm using Abstract Factory in my payment system:

public abstract class Payment : Entity

    {
        protected Payment(DateTime paidDate, DateTime expiredDate, decimal total, decimal totalPaid, string payer, Document document, Address address, Email email)
        {
            Number = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10).ToUpper();
            PaidDate = paidDate;
            ExpiredDate = expiredDate;
            Total = total;
            TotalPaid = totalPaid;
            Payer = payer;
            Document = document;
            Address = address;
            Email = email;

            AddNotifications(new Contract<Payment>()
                .Requires()
                .IsLowerOrEqualsThan(0, Total, "Payment.Total", "O total não pode ser zero")
                .IsGreaterOrEqualsThan(Total, TotalPaid, "Payment.Total", "O Valor pago é menor que o valor do pagamento")
                );
        }

        public string Number { get; private set; }
        public DateTime PaidDate { get; private set; }
        public DateTime ExpiredDate { get; private set; }
        public decimal Total { get; private set; }
        public decimal TotalPaid { get; private set; }
        public string Payer { get; private set; }
        public Document Document { get; private set; }
        public Address Address { get; private set; }
        public Email Email { get; private set; }

    }
 public class CreditCardPayment : Payment
    {
        public CreditCardPayment(string cardHolderName, string cardNumber, string lastTransactionNumber, DateTime paidDate, DateTime expiredDate, decimal total, decimal totalPaid, string payer, Document document, Address address, Email email) : base(paidDate, expiredDate, total, totalPaid, payer, document, address, email)
        {
            CardHolderName = cardHolderName;
            CardNumber = cardNumber;
            LastTransactionNumber = lastTransactionNumber;
        }

        public string CardHolderName { get; private set; }
        public string CardNumber { get; private set; }
        public string LastTransactionNumber { get; private set; }
    }

My real doubt is how do I map this inside EF Core in the DbSet part

because when I try to map the class to be implemented by the abstract, it gives an error when I upload the dotnet ef migrations add

public DbSet<CreditCardPayment> creditCardPayment{ get; set; }
No suitable constructor was found for entity type 'CreditCardPayment'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'document', 'address', 'email' in 'CreditCardPayment(string cardHolderName, string cardNumber, string lastTransactionNumber, DateTime paidDate, DateTime expiredDate, decimal total, decimal totalPaid, string payer, Document document, Address address, Email email)'.

He brings me this would i have to do

public DbSet<Payment> Payments{ get; set; }

also?

in this case, what is the best way to implement the Abstract Factory pattern in the EF CORE

in this case, what is the best way to implement the Abstract Factory pattern in the EF CORE

CodePudding user response:

EF requires an empty constructor, always, so you need to either add a public or a protected empty constructor for when the DbSet is created it woul dbe able to set properties accordingly.

Your CreditCardPayment is also not passing the properties to the base class. One thing you could do is change to something like this: (I'll omit a few things for brevity)

public abstract class Payment : Entity
{
    protected Payment() { }

    public Payment(DateTime paidDate, DateTime expiredDate, decimal total, decimal totalPaid, string payer, Document document, Address address, Email email)
    {
        // all properties here
    }
}

public class CreditCardPayment : Payment
{
    protected CreditCardPayment() { }

    public CreditCardPayment(DateTime paidDate, DateTime expiredDate, decimal total, decimal totalPaid, string payer, Document document, Address address, Email email)
        : base(paidDate, expiredDate, total, totalPaid, payer, document, address, email)
    {
        // the other 3 properties from credit card payment
    }
}

One other option is to map payment as a owned type instead of using inheritance. That would give you a navigation property instead and the mapping is quite different as well. The rule of having an empty constructor still applies.

public class CreditCardPaymentConfiguration : IEntityTypeConfiguration<CreditCardPayment>
{
    public void Configure(EntityTypeBuilder<CreditCardPayment> builder)
    {
        builder
            .OwnsOne(x => x.PaymentInfo);
    }
}

public class Payment
{

}

public class CreditCardPayment
{
    public string PropertyX { get; set; }
    public Payment PaymentInfo { get; set; }
}

Same strategy for Address and Email for example.

  • Related