EF Core question regarding relations

Tobias Groeneveld | TendenZ 1 Reputation point
2021-01-20T08:21:36.483+00:00

I'm building a ticket system.

I have two models: User and Ticket. A user can have multiple tickets, and is bound to the ticket via the Customer_Id field. Another user, with the role of Practitioner, can also be assigned to the ticket, via the Practitioner_Id field.

Here's a simplified version of those classes:

  public class User
    {
        public long UserId { get; set; }
    }




public class Ticket
{
    public long TicketId { get; set; }

    [ForeignKey("Customer")]
    public long Customer_Id { get; set; } //User.UserId (the customer)
    public User Customer { get; set; }

    [ForeignKey("Practitioner")]
    public long? Practitioner_Id { get; set; }// User.UserId (the practitioner)
    public User Practitioner { get; set; }
}

Now so far so good. When a migration is created, there's a foreign key for both Customer_Id and Pratitioner_Id to the Users table.

Now I want to have a List<Ticket> on the user model, so I can write a seeder for users with some tickets.
But how do I make clear that that List<Ticket> must refer to the tickets for which Customer_Id is equal to that user's UserId?

in other words:

public class User
{
    public long UserId { get; set; }
    public List<Ticket> tickets {get;set;} // must do: select * from tickets where Customer_Id = <this.UserId>
}
Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
717 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Tobias Groeneveld | TendenZ 1 Reputation point
    2021-01-22T11:16:54.207+00:00

    Hi Daniel,

    with a seeder class you can initialize a database's content, so if you spin up a development environment with your sourcecode and database, the seeder class inserts data for you so you don't have to insert test records yourself every time.

    In this case, I like the seeder to be able to insert a few test-users with each a few tickets. I've done this in the past with other projects like this:

    using BasicAPI.EFModels;
    using BasicAPI.EFModels.TestModels;
    using BasicAPI.Enums;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace BasicAPI.Seeders
    {
        public class Seeder // SIMPLYFIED
        {
            private MyDBContext _context;
    
            public Seeder(MyDBContext c)
            {
                _context = c;
            }
    
            public async Task Seed()
            {
    
                bool changesMade = false;
    
                if (!_context.users.Any())
                {
                    _context.users.AddRange(_users);
                    changesMade = true;
                }
    
    
    
                if (changesMade)
                    await _context.SaveChangesAsync();
                }
    
            }
    
    
    
            List<User> _users
            {
                get
                {
                    List<User> result = new List<User>();
    
                    // TEST USER
                    User customer = new User()
                    {
                        firstName = "Cus",
                        lastName = "Tomer",
                        userName = "customer",
                        passWord = "testtest",
    
                        // THE CODE BELOW WORKS, EACH TestObject AUTOMATICALLY GETS AN ID, AND AUTOMATICALLY GETS ITS UserId PROPERTY ASSIGNED TO 
                        // THE UserId OF THE USER WHICH IS INSERTED IN THE SAME STATEMENT.:
                        // THIS WORKS BECAUSE IT'S IMMEDIATELY OBVIOUS THAT TestObject.UserId MAPS TO User.UserId.
    
                        TestObjects = new List<TestObject>() {
                            new TestObject
                            {
                                Test = "A test object",
                                CreateDate = DateTime.Now
                            },
                            new TestObject
                            {
                                Test = "Another test object",
                                CreateDate = DateTime.Now
                            }
                        }
    
                        // HOWEVER FOR MY TICKET CLASS IT'S NOT WORKING BECAUSE A TICKET DOES NOT HAVE A UserId, BUT A CustomerId AND A PractitionerId.
                        // SO HOW DO I LET EF.CORE KNOW THAT WHEN I MAKE A List<Ticket>, THAT IS NEEDS TO GET THE TICKETS BASED ON Ticket.CustomerId = this.UserId ?
                    };
    
                    customer.HashPassword();
                    result.Add(customer);
    
                    return result;
                }
            }
    
    
        }
    
        public class TestObject // SIMPLYFIED
        {
            public long TestObjectId { get; set; }
    
            public long UserId { get; set; }
            public User User { get; set; }
        }
    
        public class User // SIMPLYFIED
        {
            public long UserId { get; set; }
    
            public List<TestObject> TestObjects { get; set; }
        }
    }