LastBye
LastBye

Reputation: 1173

Code-First relationship -getting error about Multiplicity

It should be a simple question, I didn't understand why that happens :

Error :

When trying to generate the model of these via Power tools I'm getting this error, I got similar error also while I was trying to add a migration about these in another project.

Activity_ActivityResult_Target: : Multiplicity is not valid in Role 'Activity_ActivityResult_Target' in relationship 'Activity_ActivityResult'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.

Here we have 2 simple classes with a relationship to be used in code-fisrt strategy.

Desired: Activity 1 ----> ActivityResult 0-1

Whole code:

   public class Activity 
    {
        [Key]
        public int Id { get; set; }
        public DateTime? ActivityDate{ get; set;}

        // Tested with and without these commented part, I didn't think it should be
        //[ForeignKey("ActivityResult")]
        //public int? ActivityResultId { get; set; }
       public virtual ActivityResult ActivityResult { get; set; }
    }


    //---------------

    public class ActivityResult //: Entity
    {

        [Key]
        public int Id { get; set; }
        public int Score1 { get; set; }
        public int Score2 { get; set; }

        [ForeignKey("Activity")]
        [Required]
        public int ActivityId { get; set; }
        public virtual Activity Activity { get; set; }
    }

// ---------------

    public class Context : DbContext
    {
        public DbSet<Activity> Activities { get; set; }
        public DbSet<ActivityResult> ActivityResults { get; set; }
    }

Why? what is the solution?

Upvotes: 0

Views: 52

Answers (2)

tschmit007
tschmit007

Reputation: 7800

@Dismissile is right, but imho the right code is:

public class Activity {
        [Key]
        public int Id { get; set; }
        public DateTime? ActivityDate { get; set; }
        public virtual ActivityResult ActivityResult { get; set; }
    }


    //---------------

    public class ActivityResult {

        [Key]
        public int Id { get; set; }
        public int Score1 { get; set; }
        public int Score2 { get; set; }

        //public int ActivityId { get; set; }
        [ForeignKey("Id")]
        [Required]
        public virtual Activity Activity { get; set; }
    }

giving the following tables:

CREATE TABLE [dbo].[Activities](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ActivityDate] [datetime] NULL,
 CONSTRAINT [PK_dbo.Activities] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)

and

CREATE TABLE [dbo].[ActivityResults](
    [Id] [int] NOT NULL,
    [Score1] [int] NOT NULL,
    [Score2] [int] NOT NULL,
 CONSTRAINT [PK_dbo.ActivityResults] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)

Upvotes: 1

Dismissile
Dismissile

Reputation: 33071

In a one-to-one relationship, the foreign key is also the primary key.

You need to change ActivityResult to remove the Id property and only have ActivityId. It will have both [Key] and [ForeignKey]:

public class ActivityResult //: Entity
{

    [Key]
    [ForeignKey("Activity")]
    [Required]
    public int ActivityId { get; set; }
    public int Score1 { get; set; }
    public int Score2 { get; set; }

    public virtual Activity Activity { get; set; }
}

Here is how Entity Framework will create the tables using Migrations. You will notice that ActivityResults does not define ActivityId as an Identity. This is because it cannot be auto generated. In order to be one-to-one it must have a matching row in Activities. It is the primary key so it is unique. If you had both ActivityId and Id and Id was the primary key, then you really have a one to many relationship.

CreateTable(
    "dbo.Activities",
    c => new
    {
        Id = c.Int(nullable: false, identity: true),
        ActivityDate = c.DateTime(),
    })
    .PrimaryKey(t => t.Id);

CreateTable(
    "dbo.ActivityResults",
    c => new
    {
        ActivityId = c.Int(nullable: false),
        Score1 = c.Int(nullable: false),
        Score2 = c.Int(nullable: false),
    })
    .PrimaryKey(t => t.ActivityId)
    .ForeignKey("dbo.Activities", t => t.ActivityId)
    .Index(t => t.ActivityId);

Upvotes: 2

Related Questions