ASP.NET Core Web API / Angular- Create & Set Relationships in Single Request/Transaction

Viewed 386

The crux of this is how should I handle a situation in which there is a one to one relationship and a one to many relationship being created on a newly created entity in a single request or transaction.

Concrete Example:

  • Person 1 - N Emails
  • Person 1 - 1 Email (Default Email) [Required]

I want to handle the creation of the person, emails, and setting of the default email in a single transaction/request to the server.

Note: I am using ASP.Net Core 3.1 Web API, EF Core, and Angular 2+.

Problem: Once I submit the request with all of the relationships/data I have no way of actually knowing which of the new emails is the default since they don't have ids yet to compare against. The ids are auto-incrementing int as of now and are created on insert. (I know I could hack this by comparing email values such as the address but this isn't a good route in general use.)

Potential Solutions:

  1. Switching the primary keys from int to Guid(s) and creating client side ids for all of these objects so then in the API controller when I create the emails and set the default, I know the email that corresponds to the list just inserted and the relationships will be saved correctly. (I come from an Ember Data background so this seems the most natural to me, but am open to other solutions.)

  2. Use a view model/custom request that allows me to send extra data with the email for this request to denote this is the default email. I don't particularly like this approach as I think this will get messier the more instances of these kind of relationships exist.

I would love to hear some thoughts on potential solutions and other approaches to this problem, thanks in advance!

Edit: Added Class Examples (Configured Model/Relationships w/ Fluent API)

I know that I don't need the join entity as its not a many - many, but it may be useful down the line for adding extra data/keeps tables clean when many things may end up joining on the email table, and isn't the issue at hand.

Draft of the Data Models as I don't have the exact files available right now.

public class Person
{

    public int Id { get; set; }
    public string Name { get; set; }

    public int DefaultEmailId { get; set; }
    public Email DefaultEmail { get; set; }

    public virtual ICollection<PersonEmail> PersonEmails { get; set; }

}

public class Email
{

    public int Id { get; set; }
    public string Address { get; set; }

    public virtual ICollection<PersonEmail> EmailPersons { get; set; }
}

public class PersonEmail
{
    public int Id { get; set; }

    public int EmailId { get; set; }
    public Email Email { get; set; }

    public int PersonId { get; set; }
    public Person person { get; set; }

}
1 Answers

After some thought and the suggestion from @GertArnold this is the solution I'm going with at the moment.

I will add a separate column/field that will have a generated client id, Guid, from their I can know in the API controller or front end components what email is the default at any time.

public Guid ClientId { get; set; } // or some other name

This would allow me to keep the primary key as an int but have a stable identifier for business logic on the frontend and backend. It will also allow me the flexibility to transition to using the Guid as the primary key and keep the int id as an indexing column for db performance, if ever deemed necessary.

The only problem I foresee with this is the strangeness/confusion of comparing client ids versus primary key int ids, in certain contexts, such as: queries, business, or front end logic.

Related