I have a method that is responsible for receiving an object and perform the information saved with Entity Framwork, using the Repository pattern. The issue is that this object is, basically, a DTO. The information contained in this object must be assigned to the models managed by the data layer, which is a bit confusing to me with respect to the way of making said assignments, considering that there are conditions for some of them.
public int RegisterParticipant(ParticipantDTO participant)
{
try
{
EventoParticipante participante = new EventoParticipante();
if(participant.Token != null)
{
var result = RegistrarPagoEnLinea(participant);
participante.PagoEnLinea = true;
}
else
{
participante.PagoEnLinea = false;
participante.TransaccionFecha = DateTime.Now;
participante.TransaccionCodigo = participant.PaymentRefNumber;
}
participante.PersonaId = CreateNaturalPerson(participant).Id;
participante.InstitucionId = short.Parse(CreateInstitution(participant).ToString());
participante.EventoId = participant.EventId;
participante.TipoParticipanteId = _attendeeTypeRepository.SingleOrDefault(x => x.Nombre == participant.TypeParticipant).Id;
participante.MontoPago = decimal.Parse(participant.Ammount);
participante.Asistio = false;
participante.FechaRegistro = DateTime.Now;
participante.MontoPago = decimal.Parse(participant.Ammount) - 100;
_eventAttendeeRepository.Add(participante);
_eventAttendeeRepository.SaveChanges();
Evento eventParticipant = _eventRepository.Get(participant.EventId);
if (participant.CompanionName != null && !string.IsNullOrEmpty(participant.CompanionName))
{
Persona companion = new Persona();
companion.Nombres = participant.CompanionName;
companion.Apellidos = participant.CompanionLastName;
companion.NumeroDocumento = participant.CompanionIdentity;
companion.Ciudad = participant.AttendeeCity;
companion.Activo = true;
companion.UsuarioCreacion = "demo";
companion.UsuarioModificacion = "demo";
companion.FechaCreacion = DateTime.Now;
companion.FechaModificacion = DateTime.Now;
_personRepository.Add(companion);
_personRepository.SaveChanges();
EventoParticipante companionParticipant = new EventoParticipante();
companionParticipant.PersonaId = companion.Id;
companionParticipant.EventoParticipanteId = participante.Id;
companionParticipant.EventoId = participante.EventoId;
companionParticipant.MontoPago = decimal.Parse((100.00).ToString());
companionParticipant.TipoParticipanteId = 4;
companionParticipant.InstitucionId = participante.InstitucionId;
companionParticipant.Asistio = false;
companionParticipant.FechaRegistro = DateTime.Now;
_eventAttendeeRepository.Add(companionParticipant);
_eventAttendeeRepository.SaveChanges();
}
if (participant.InvoiceIdentity != null && !string.IsNullOrEmpty(participant.InvoiceIdentity))
{
CreateInvoice(participant, participante);
MailHelper.SendMail(MailAction.EventRegisterSuccessWithInvoice, eventParticipant, participant, _countryRepository.Get(participant.AttendeeCountryId).Nombre, _countryRepository.Get((int)participant.InvoiceCountryId).Nombre);
}
else
MailHelper.SendMail(MailAction.EventRegisterSuccess, eventParticipant, participant, _countryRepository.Get(participant.AttendeeCountryId).Nombre);
return 0;
}
catch (Exception e)
{
return 1;
}
}
As you can see, the method is excessively long. I understand that a method should be in charge of a specific function, so I know that it is wrong from that point.
To try to diminish its extension (and the possibility of errors in it) I have separated certain assignment tasks into methods within the same class, as in the case of CreateNaturalPerson
(yes, the method was even longer). I thought to do the same with the IF where the values are assigned to Persona
and EventoParticipante
, but I think it would be to fall into the same. Is there any design pattern or advice for the above mentioned?
SaveChanges
twice. What happens if the first call succeeds and the second fails? Your db would be left in an invalid state. Also, using return codes is not a c# convention. Just let exceptions be thrown and caught by a global handler. Wrapping huge chunks of code intry/catch
without logging the exception will just silently mask them, which is really bad. \$\endgroup\$SaveChanges
saved the data in the database for each context. I considered that, having an instance of my mainRepository
class for each model of my database, I should make the call each time I made anAdd
. In addition, I had to obtain the ID of the saved item in order to assign it to a property of the following models. Is there any way to do it in a more effective way and considering everything you tell me? \$\endgroup\$null
and thenstring.IsNullOrEmpty
:if (participant.CompanionName != null && !string.IsNullOrEmpty(participant.CompanionName))
?string.IsNullOrEmpty
already include thenull
check. \$\endgroup\$