Entity Framework One to one property not saving

one-to one relationship entity framework core code first
entity framework one-to zero or one
entity framework one-to-many
entity framework core one-to zero or one
one to one relationship entity framework database first
entity framework core one-to-many
the child/dependent side could not be determined for the one-to-one relationship between
entity framework one-to-one optional

I'm having troubles figuring out why I can save directly to the collection with ontext.CommunicationPreferences.Add. But Trying to add to guest.communicationPreference does not work.

Am I missing some mapping somewhere? Thanks!

Code

    [TestMethod]
    public void TestMethod1()
    {
        var guests = new Context().Guests.ToList();
        var communicationTypes = new Context().CommunicationTypes.ToList();
        var communicationPreferences = new Context().CommunicationPreferences.ToList();

        using (var context = new Context())
        {
            var guest = guests.FirstOrDefault(x => x.Id == 1);

            // This works
            context.CommunicationPreferences.Add(new CommunicationPreference(1, guest.Id, communicationTypes.First().Id));

            // This does not work - why? :(
            guest.CommunicationPreference = new CommunicationPreference(1, guest.Id, communicationTypes.First().Id);

            context.SaveChanges();
        }
    }
    public class CommunicationPreference
    {
        public CommunicationPreference()
        {

        }

        public CommunicationPreference(int time, int guestId, int communicationTypeId)
        {
            Time = time;
            GuestId = guestId;
            CommunicationTypeId = communicationTypeId;
        }

        public int GuestId { get; set; }
        public int? CommunicationTypeId { get; set; }
        public virtual CommunicationType CommunicationType { get; set; }
        public virtual Guest Guest { get; set; }
        public int? Time { get; set; }
    }

    public class CommunicationType
    {
        public CommunicationType()
        {
        }

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

    public class Guest
    {
        public Guest()
        {

        }

        public int Id { get; set; }
        public string FirstName { get; set; }
        public virtual CommunicationPreference CommunicationPreference { get; set; }
    }

    public class Context : DbContext
    {
        public Context() : base("Context")
        {
        }

        public DbSet<Models.Guest> Guests { get; set; }
        public DbSet<Models.CommunicationType> CommunicationTypes { get; set; }
        public DbSet<Models.CommunicationPreference> CommunicationPreferences { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            this.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

            modelBuilder.Entity<Models.CommunicationPreference>().HasKey(t => t.GuestId);
            modelBuilder
                .Entity<Models.CommunicationPreference>()
                .HasRequired<Models.Guest>(x => x.Guest)
                .WithOptional(x => x.CommunicationPreference);
        }
    }

Database

CREATE TABLE [dbo].[Guest](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [FirstName] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Guest] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[CommunicationType](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
 CONSTRAINT [PK_CommunicationType] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[CommunicationPreference](
    [Time] [int] NULL,
    [CommunicationTypeId] [int] NULL,
    [GuestId] [int] NOT NULL,
 CONSTRAINT [PK_CommunicationPreference] PRIMARY KEY CLUSTERED 
(
    [GuestId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[CommunicationPreference]  WITH CHECK ADD  CONSTRAINT [FK_CommunicationPreference_CommunicationType] FOREIGN KEY([CommunicationTypeId])
REFERENCES [dbo].[CommunicationType] ([Id])
GO

ALTER TABLE [dbo].[CommunicationPreference] CHECK CONSTRAINT [FK_CommunicationPreference_CommunicationType]
GO

ALTER TABLE [dbo].[CommunicationPreference]  WITH CHECK ADD  CONSTRAINT [FK_CommunicationPreference_Guest] FOREIGN KEY([GuestId])
REFERENCES [dbo].[Guest] ([Id])
GO

ALTER TABLE [dbo].[CommunicationPreference] CHECK CONSTRAINT [FK_CommunicationPreference_Guest]
GO

You are loading your data in 4 different context instances....

This:

    var guests = new Context().Guests.ToList(); // Context 1
    var communicationTypes = new Context().CommunicationTypes.ToList(); // Context 2
    var communicationPreferences = new Context().CommunicationPreferences.ToList(); // Context 3

    using (var context = new Context()) // Context 4
    {
        var guest = guests.FirstOrDefault(x => x.Id == 1);

        // This works
        context.CommunicationPreferences.Add(new CommunicationPreference(1, guest.Id, communicationTypes.First().Id));

        // This does not work - why? :(
        guest.CommunicationPreference = new CommunicationPreference(1, guest.Id, communicationTypes.First().Id);

        context.SaveChanges();
    }

Put everything in the same context because Context #4 (using one) doesn't know about entities from Context 1 (guests)

This would work:

using (var context = new Context())
{
    var guests = context.Guests.ToList();
    var communicationTypes = context.CommunicationTypes.ToList();
    var communicationPreferences = context.CommunicationPreferences.ToList();

    var guest = guests.FirstOrDefault(x => x.Id == 1);

    guest.CommunicationPreference = new CommunicationPreference(1, guest.Id, communicationTypes.First().Id);

    context.SaveChanges();
}

Configure One-to-One relationship in Code First Entity Framework, Learn how to configure one-to-one relationship in Entity Framework 6 code-first navigation property in Student entity as optional (not required when saving the� We can configure a one-to-One relationship between entities using Fluent API where both ends are required, meaning that the Student entity object must include the StudentAddress entity object and the StudentAddress entity must include the Student entity object in order to save it. Note:One-to-one relationships are technically not possible in MS


I am ignoring every other aspects except why not updating.

When you adding entity by add() it set state of the that entity to modified automatically but if you not using add() then You need to modify your state of entity manually.

context.Entry(guest.CommunicationPreference).State = EntityState.Modified;

You need to add above line before saving changes.

Configure One-to-One Relationships using Fluent API in Entity , However, if the key or foreign key properties do not follow the convention, then you can use data annotation attributes or Fluent API to configure a one-to-one� Entity Framework Core introduced default conventions which automatically configure a One-to-One relationship between two entities (EF 6.x or prior does not support conventions for One-to-One relationship). In EF Core, a one-to-one relationship requires a reference navigation property at both sides. The following Student and StudentAddress


in this block of code

  context.CommunicationPreferences.Add(new CommunicationPreference(1, guest.Id, communicationTypes.First().Id));

        // This does not work - why? :(
        guest.CommunicationPreference = new CommunicationPreference(1, guest.Id, communicationTypes.First().Id);

        context.SaveChanges(); 

The "guest" is not relate or not in work context of your "Context" instance so guest never save. I hope you get it.

Configuring One To One Relationships In Entity Framework Core , If it is unable to do this, either because the foreign key property name does not follow convention, or because it has not been included in the model, an error� Adding a related entity. If you reference a new entity from the navigation property of an entity that is already tracked by the context, the entity will be discovered and inserted into the database. In the following example, the post entity is inserted because it is added to the Posts property of the blog entity which was fetched from the database.


Modifying data via the DbContext, When you alter property values on a tracked entity, the context changes the Any related objects will not be tracked. Since the ChangeTracker is unaware of which properties were modified, the context will issue an SQL statement updating all var context = new TestContext();; var author = new Author {; AuthorId = 1,� Again, SqlBulkCopy is a hands-down leader. The source code of the test application is available at GitHub.. Conclusion. When working with the context, containing large number of objects (10³ and more), refusal of the Entity Framework infrastructure (adding to context + saving the context) and switch to SqlBulkCopy for adding records to DB can improve performance in dozens, and even hundreds


One to One, Learn Entity Framework one-to-one-relationship by example. an exception when the AuthorBiography entity is saved without the Author navigation property. No foreign key property. While it is recommended to have a foreign key property defined in the dependent entity class, it is not required. If no foreign key property is found, a shadow foreign key property will be introduced with the name <navigation property name><principal key property name> or <principal entity name><principal key property name> if no navigation is present on the dependent


Saving Related Data, If you reference a new entity from the navigation property of an entity that is already tracked by the context, the entity will be discovered and For optional relationships, cascade delete is not configured by default, but the� Generally, you don't need to configure one-to-one relationships manually because EF Core includes Conventions for One-to-One Relationships. However, if the key or foreign key properties do not follow the convention, then you can use data annotation attributes or Fluent API to configure a one-to-one relationship between the two entities.