Firstly, I'm relatively new to Entity Framework stuff and WebAPI but, I'm currently writing a Web API for fun that involves a person being able to create a master "business" account that's able to create 'Businesses' and create and attach child accounts to them. There are separate tables that keep track of the businesses created under business accounts and a list of Workers that are attached to those businesses.
Given the following classes/code:
Business Class:
public class Business
{
public int Id { get; set; }
public string BusinessAccount { get; set; }
public string BusinessName { get; set; }
public List<Worker> Workers { get; set; }
}
SchedulerDbContext:
public class SchedulerDbContext : DbContext
{
public SchedulerDbContext()
: base("SchedulerDbContext")
{
}
public virtual DbSet<Business> Businesses { get; set; }
public virtual DbSet<Worker> Workers { get; set; }
}
BusinessController: (only relevant section shown)
[Route("Create")]
public IHttpActionResult Create(string name)
{
if (String.IsNullOrWhiteSpace(name))
{
ModelState.AddModelError("BusinessNameError", "Invalid Business Name Entered.");
return BadRequest(ModelState);
}
Business business = new Business()
{
BusinessName = name,
BusinessAccount = User.Identity.Name,
Workers = new List<Worker>() //<----a
};
using (var db = new SchedulerDbContext())
{
db.Businesses.Add(business); //<----b
db.SaveChanges();
}
return Ok(business);
}
UserController: (only relevant section)
[Route("Register")]
public async Task<IHttpActionResult> Register(UserModel userModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
AccountUser user = new AccountUser
{
UserName = userModel.UserName,
Email = userModel.Email,
BusinessAccount = User.Identity.Name
};
IdentityResult result = await this.SchedUserManager.RegisterUser(user, userModel);
IHttpActionResult errorResult = GetErrorResult(result);
if (errorResult != null)
{
return errorResult;
}
result = await this.SchedUserManager.AddToRoleAsync(user.Id, defaultRole);
errorResult = GetErrorResult(result);
if (errorResult != null)
{
return errorResult;
}
using (var db = new SchedulerDbContext())
{
var query = from record in db.Businesses
where record.Id == userModel.BusinessId
select record;
var business = query.First();
var worker = new Worker()
{
FirstName = userModel.FirstName,
LastName = userModel.LastName,
Email = userModel.Email
};
if (business.Workers == null) { business.Workers = new List<Worker>(); } //<----c
business.Workers.Add(worker); //<----d
db.SaveChanges();
}
return Ok();
}
Now with the code out of the way. There were multiple spots that I marked with arrows. Now the questions I have are...
When creating a Busines in the Create() function of the BusinessController, I assigned the Workers property a new List as seen at //<----a. So after that, it is added to the SchedulerDbContext at //<----b and changes saved.
Now, when creating a user account to attach to that business in the UserController's Register() function I ran into an issue. If running the line at arrow //<----d is done without the line at //<----c existing, I get a NullReferenceException.
What I'm curious about is why the line at //<----a didn't fix this? I'm pretty sure there isn't technically a record to assign to, but is checking to see if it's null (like at //<----c) the cleanest way to handle it? Part of me imagined EF to magically handle this for me. Is there a better way? It just seems to me an odd spot to assign a new List if it's empty, like it should be done somewhere else.