J.Doe
J.Doe

Reputation: 155

EF Code First: Model issue with cross relations of the sub objects

I use Entity Framework Code First and I have need to write down the object into the DB and having a strange issue which makes me think that my Entity Model is probably wrong.

The object includes 2 sub-object of the Position type:

var request = new Request();
request.StartPosition = new Position();
request.EndPosition = new Position();
_context.Requests.Insert(request);

Here's my model:

[Table("Requests")]
public class Request
{
    [Key]
    public Guid Id { get; set; }

    public Guid ProductId { get; set; }


    public virtual int PositionId { get; set; }

    [ForeignKey("PositionId")]
    public virtual Position StartPosition { get; set; }

    [ForeignKey("PositionId")]
    public virtual Position DestinationPosition { get; set; }
}//class


[Table("Positions")]
public class Position
{
    [Key]
    public int Id { get; set; }

    public double X { get; set; }

    public double Y { get; set; }

    public virtual ICollection<Request> Requests { get; set; }


    public Position()
    {
        Requests = new List<Request>();
    }
}

And this is the exception I receive: {"Referential integrity constraint violation. A Dependent Role has multiple principals with different values."}

Upvotes: 1

Views: 48

Answers (1)

travis.js
travis.js

Reputation: 5281

I believe you class design could look something like this...

[Table("Requests")]
public class Request
{
    [Key]
    public Guid Id { get; set; }

    public Guid ProductId { get; set; }


    public virtual int StartPositionId { get; set; }

    public virtual int DestinationPositionId { get; set; }

    [ForeignKey("StartPositionId")]
    public virtual Position StartPosition { get; set; }

    [ForeignKey("DestinationPositionId")]
    public virtual Position DestinationPosition { get; set; }
}


[Table("Positions")]
public class Position
{
    [Key]
    public int Id { get; set; }

    public double X { get; set; }

    public double Y { get; set; }

    public virtual ICollection<Request> StartPositionRequests { get; set; }

    public virtual ICollection<Request> DestinationPositionRequests { get; set; }

    public Position()
    {
        StartPositionRequests = new List<Request>();
        DestinationPositionRequests = new List<Request>();
    }
}

Add you DbContext may need some additional information to define the relationships. On EF Core, this works:

public class MyDbContext : DbContext
{
    public DbSet<Request> Requests { get; set; }
    public DbSet<Position> Positions { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"...");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Position>().HasMany(x => x.StartPositionRequests).WithOne(x => x.StartPosition).OnDelete(DeleteBehavior.Restrict);
        modelBuilder.Entity<Position>().HasMany(x => x.DestinationPositionRequests).WithOne(x => x.DestinationPosition).OnDelete(DeleteBehavior.Restrict);
    }
}

Upvotes: 1

Related Questions