0

I have the two table like this:

public class NotificationType : AuditableEntity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string Id { get; set; }
    public string Channel { get; set; }
}
public class NotificationSubscription : AuditableEntity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string Id { get; set; }
    public string UserId { get; set; }
    public string NotificationTypeId { get; set; }
    public NotificationType NotificationTypes { get; private set; } = new();
}

When I am seeding the data I am doing like this:

context.NotificationTypes.Add(new NotificationType
{
    Id = "4C1B3788-3CDE-4F6D-82EB-7B4B71A601EF",
    Channel = "Email",
});
await context.SaveChangesAsync();

context.NotificationSubscriptions.Add(new NotificationSubscription
{    
    Id = "5A4944C7-9FD8-4BC3-81F7-2ED92729962B",
    UserId = "081C459B-77D3-45F3-B26A-6879EAE53FC2",
    NotificationTypeId = "4C1B3788-3CDE-4F6D-82EB-7B4B71A601EF",
});
await context.SaveChangesAsync();

DbContext


public DbSet<NotificationType> NotificationTypes { get; set; }
public DbSet<NotificationSubscription> NotificationSubscriptions { get; set; }

public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
    foreach (Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<AuditableEntity> entry in ChangeTracker.Entries<AuditableEntity>())
    {
        switch (entry.State)
        {
            case EntityState.Added:
                entry.Entity.CreatedBy = _currentUserService.UserId;
                entry.Entity.Created = _dateTime.Now;
                break;

            case EntityState.Modified:
                entry.Entity.LastModifiedBy = _currentUserService.UserId;
                entry.Entity.LastModified = _dateTime.Now;
                break;
        }
    }

    var result = await base.SaveChangesAsync(cancellationToken);

    return result;
}

The NotificationTypes get saved without any problem, but while trying to save to the NotificationSubscriptions, got the error:

Unable to track an entity of type 'NotificationType' because its primary key property 'Id' is null.

I guess the issue is due to the mapping from the one-to-one relationships. But I don't know how to exactly solve the issues. I don't want to add NotificationType while adding the NotificationTypes, I just want to reference it with the NotificationTypeId.

Please guide me with the workaround or the possible solution.

Rasik
  • 1,961
  • 3
  • 35
  • 72
  • (little side note: your ids look very much like GUIDs. there's a native `Guid`-datatype that's better for handling those than strings - for obvious reasons) could you please provide the _complete_ code that's saving those entities, so we can see the relation between them as well as when you commit any changes? – Franz Gleichmann Jun 10 '21 at 07:52
  • In most cases it's better to work with the objects instead of the Ids. So don't assign the NotificationTypeId but NotificationType – Klamsi Jun 10 '21 at 07:54
  • @FranzGleichmann yeah the Ids are `Guid`, and i have updated the code to show the DbContext as well. That is only thing in my DbContext. I have no configuration in model builder. – Rasik Jun 10 '21 at 07:57
  • @Klamsi `don't assign the NotificationTypeId but NotificationType` yeah I would like to do that. but how can I? – Rasik Jun 10 '21 at 08:05
  • i actually meant more of the seeding code.. the stuff around your call to `context.NotificationTypes.Add` – Franz Gleichmann Jun 10 '21 at 08:06
  • it is just calling the `await context.SaveChangesAsync();` after the addition of the data. – Rasik Jun 10 '21 at 08:08
  • Never do this `public NotificationType NotificationTypes { get; private set; } = new();` - see the accepted answer to the post marked as duplicate. – Ivan Stoev Jun 10 '21 at 09:57
  • I didn't get any idea how the question is duplicate. – Rasik Jun 10 '21 at 09:58
  • 1
    Because the issue is caused by the fact that you are initializing **reference** *navigation property*. The answer of the linked post explains why you should not do that. If it's still unclear, the problem is `= new();`. Remove it and problem is gone. – Ivan Stoev Jun 10 '21 at 16:03

1 Answers1

0

You also need to pass NotificationType object as it seems it is taking its value as null for primary key.

Change your model to

public class NotificationSubscription : AuditableEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; set; }
public string UserId { get; set; }
public NotificationType NotificationTypes { get; private set; }
}

Now here, set the NotificationTypes object value

context.NotificationSubscriptions.Add(new NotificationSubscription
{    
   Id = "5A4944C7-9FD8-4BC3-81F7-2ED92729962B",
   UserId = "081C459B-77D3-45F3-B26A-6879EAE53FC2",
   NotificationType= new NotificationType{
   Id=1,
   channel="Email"
 },
});