简体   繁体   中英

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();

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();
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM