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();
                            }
                        }
                    }
                }
            }
        }
\$\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\$ – BCdotWEB Apr 17 '20 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\$ – iSR5 Apr 17 '20 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\$ – Jefferson Apr 17 '20 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\$ – iSR5 Apr 17 '20 at 19:42
4
+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
{       
}
\$\endgroup\$
5
  • \$\begingroup\$ what is Schedule and is protected override void preserveChildIds() the model? \$\endgroup\$ – Jefferson Apr 23 '20 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\$ – Aron Apr 26 '20 at 20:15
  • \$\begingroup\$ and abstract class Component is the model? \$\endgroup\$ – Jefferson Apr 27 '20 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\$ – Aron Apr 27 '20 at 18:11
  • \$\begingroup\$ Thank you for accepting the answer, and the bounty. \$\endgroup\$ – Aron Apr 28 '20 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.

\$\endgroup\$
1
  • \$\begingroup\$ Using LINQ to SQL \$\endgroup\$ – Jefferson Apr 17 '20 at 13:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.