3
\$\begingroup\$

I have this code that I am using to update OriginalId using the Id value. I there a better way to do this then using all the loops?

Controller

TemplatesDataService.UpdateRegimenCodeId(template.Regimens);

Interface

void UpdateDosageInstructionsCodeId(IEnumerable<Regimen> Regimens);

DataService

public void UpdateDosageInstructionsCodeId(IEnumerable<Regimen> regimens)
 {
 if (regimens != null)
 {
 foreach (var regimen in regimens)
 {
 Debug.Write(string.Format("{0} {1}", "regimenId", regimen.Id));
 regimen.OriginalId = regimen.Id;
 foreach (var regimenPart in regimen.RegimenParts)
 {
 regimenPart.OriginalId = regimenPart.Id;
 Debug.Write(string.Format("{0} {1}", "regimenPart", regimenPart.Id));
 foreach (var entries in regimenPart.RegimenEntries)
 {
 entries.OriginalId = entries.Id;
 Debug.Write(string.Format("{0} {1}", "RegimenEntries", entries.Id));
 foreach (var dosage in entries.DosageInstructions)
 {
 Debug.Write(string.Format("{0} {1}", "DosageInstructions", dosage.Id));
 dosage.OriginalId = dosage.Id;
 UnitOfWork.Save();
 }
 }
 }
 }
 }
 }
asked Apr 17, 2020 at 12:15
\$\endgroup\$
4
  • \$\begingroup\$ Wouldn't this be far simpler as an SQL query? Sometimes an ORM is the wrong tool and you're better off writing a query to handle things for you. \$\endgroup\$ Commented Apr 17, 2020 at 14:30
  • \$\begingroup\$ you're trying to re-invent the wheel. you should make use of Foreign Key in your database and take advantage of the CASCADE UPDATE to update the all foreign keys whenever the primary key is updated. \$\endgroup\$ Commented Apr 17, 2020 at 19:13
  • \$\begingroup\$ @iSR5 for new records I want to use the primary key value as the OriginalId. I need to insert the values and get the Pk . \$\endgroup\$ Commented Apr 17, 2020 at 19:32
  • \$\begingroup\$ @Jefferson you could just make the column OriginalId in each table as FK of the original table, and just set CASCADE UPDATE on the FK. this should do it for you. Even if you're using ORM like EF. It should automate it for you if you have FK. \$\endgroup\$ Commented Apr 17, 2020 at 19:42

2 Answers 2

3
+50
\$\begingroup\$

I like the suggestions to let SQL do the foreign key cascading for you. Also, have you considered generating the id's outside the system (e.g. Guid.NewGuid()) and pushing them in?

Whatever the constraints and limitations you're working under, here's my take on a class hierarchy to handle your use case (via inheritance rather than encapsulation).

While it might be a bit over-designed for just handling Id's, the idea here is to create an object model upon which you can expand the application to arbitrary size. The example also aims to minimize code repetition.

using System;
using System.Collections.Generic;
using System.Diagnostics;
class App_DosageSchedule
{
 public void Run()
 {
 var regimens = new List<Regimen>();
 var schedule = new Schedule(regimens);
 schedule.PreserveIds();
 schedule.Save();
 }
} 
public abstract class Component
{
 public Guid Id { get; protected set; }
 public Guid OriginaId { get; protected set; }
 public void PreserveId()
 {
 OriginaId = Id;
 Debug.Write($"{GetType().Name} {Id}");
 }
}
public abstract class ComponentWithChildren : Component
{
 public void PreserveIds()
 {
 PreserveId();
 preserveChildIds();
 }
 protected abstract void preserveChildIds();
}
public class Schedule
{
 public List<Regimen> Regimens { get; private set; }
 public Schedule(List<Regimen> regimens) => Regimens = regimens;
 public void PreserveIds() => Regimens.ForEach(r => r.PreserveIds());
 public void Save()
 {
 ///write to SQL
 }
}
public class Regimen: ComponentWithChildren
{ 
 public List<RegimenPart> Parts { get; private set; }
 protected override void preserveChildIds() => Parts.ForEach(p => p.PreserveIds());
}
public class RegimenPart : ComponentWithChildren
{ 
 public List<DosageInstruction> Dosages{ get; private set; }
 protected override void preserveChildIds() => Dosages.ForEach(d => d.PreserveId());
}
public class DosageInstruction : Component
{ 
}
answered Apr 20, 2020 at 18:50
\$\endgroup\$
5
  • \$\begingroup\$ what is Schedule and is protected override void preserveChildIds() the model? \$\endgroup\$ Commented Apr 23, 2020 at 18:31
  • \$\begingroup\$ Hi, Since there's a collection of Regimen objects that we want to operate on, Schedule provides methods for the IEnumerable<Regimen>. protected override void preserveChildIds() is a method that exists on parent components, to "cascade" the preservation to its child records. \$\endgroup\$ Commented Apr 26, 2020 at 20:15
  • \$\begingroup\$ and abstract class Component is the model? \$\endgroup\$ Commented Apr 27, 2020 at 15:48
  • \$\begingroup\$ I would say that the collection of classes make up the model. Together they "model" the domain. In an MVC app, they could all be in the Models folder. \$\endgroup\$ Commented Apr 27, 2020 at 18:11
  • \$\begingroup\$ Thank you for accepting the answer, and the bounty. \$\endgroup\$ Commented Apr 28, 2020 at 17:55
3
\$\begingroup\$

Are you using a ORM like Entity framework? If so use navigation properties and let it resolve the dependencies for you.

UnitOfWork.Save();

This is a bad design to define unit of work. There are no clear boundries that are enforced. Plus not much Unit of work if you commit for each child at the lowest level.

Hope that can give you some pointers.

answered Apr 17, 2020 at 12:50
\$\endgroup\$
1
  • \$\begingroup\$ Using LINQ to SQL \$\endgroup\$ Commented Apr 17, 2020 at 13:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.