Barış Velioğlu
Barış Velioğlu

Reputation: 5817

Entity Framework One To One Relation Adding Entity with code first

I have two classes and their relations are as below:

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

     public int? IndicatorId { get; set; }
     public virtual Indicator Indicator { get; set; }
}

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

     public int InteractiveObjectId { get; set; }
     public virtual InteractiveObject InteractiveObject { get; set; }
}

And I configure it like

  modelBuilder.Entity<Indicator>().HasRequired(x => x.InteractiveObject)
            .WithOptional(x => x.Indicator);

It creates two tables that the table Indicator has not a nullable InteractiveObjectId, and table InteractiveObject has a nullable IndicatorId. Perfect.

But when I try to add Indicator with an InteractiveObject. The table Indicator contains the all information but the related InteractiveObject table does not contain IndicatorId. I mean IndicatorId is null on InteractiveObject table but InteractiveObjectId is not null on Indicator table

The code is like below:

  modelBuilder.Entity<Indicator>().HasRequired(x => x.InteractiveObject)
            .WithOptional(x => x.Indicator);

        var selectedInteractiveObject = DbContext.Set<InteractiveObject>().FirstOrDefault(x => x.Id == 1);

        var indicator = new Indicator { Name = "Test"};

        selectedInteractiveObject.Indicator = indicator;

        DbContext.SaveChanges();

Upvotes: 0

Views: 112

Answers (2)

Paul Kyrejto
Paul Kyrejto

Reputation: 1315

Since we have one-to-zero or one relation we don't need to define separate keys as they can share same Id, but Indicator refers to InteractiveObject. That means that InteractiveObject can exist w/o Indicator but not vice versa.

So class objects should be like this:

 public class Indicator
    {
        [ForeignKey("InteractiveObject")]
        public int Id { get; set; }

        public string Name { get; set; }

        public virtual InteractiveObject InteractiveObject { get; set; }
    }

    public class InteractiveObject
    {

        public int Id { get; set; }

        public string Name { get; set; }

        public virtual Indicator Indicator { get; set; }
    }

You should have your context class inherited from DbContext like this:

public partial class YourContext: DbContext
    {
        static YourContext() { }

        //Class constructor with Connection String name
        public YourContext() : base("name=YourConnectionString") { }

        public DbSet<Indicator> Indicators{ get; set; }
        public DbSet<InteractiveObject> InteractiveObjects { get; set; }
}

And now you can operate on its instance via disposable pattern:

using (var context = new YourContext())
{
    var selectedInteractiveObject = context.InteractiveObjects.FirstOrDefault(x => x.Id == 1);
    var indicator = new Indicator { Name = "Test" };
    selectedInteractiveObject.Indicator = indicator;
    context.SaveChanges();
}

Upvotes: 1

Jenish Rabadiya
Jenish Rabadiya

Reputation: 6766

well, You are looking for the value in wrong column.

If you have applied -Versbose flag while running migration you would have noticed following SQL statement creating foreign key constraint.

ALTER TABLE [dbo].[Indicators] ADD CONSTRAINT [FK_dbo.Indicators_dbo.InteractiveObjects_Id] FOREIGN KEY ([Id]) REFERENCES [dbo].[InteractiveObjects] ([Id])

Id column of Indicator is the foreign key so it would have value pointing to the ID of InteractiveObject.

Update

Making the Id of Indicator as foreign key also force the constraint that it is one to one or zero relationship while if IndicatorId in InteractiveObject would be the foreign key it appeared to be one to zero or many relationship.

Upvotes: 0

Related Questions