简体   繁体   中英

EF 4.1 Code first multiple one-to-many associations

Here is my model

public class Horse
{
    public int HorseId { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
    public LegType LegType { get; set; }
    public Character Character { get; set; }
    public int Hearts { get; set; }
    public bool Retired { get; set; }
    // Parents
    public Horse Sire { get; set; }
    public Horse Dam { get; set; }
    // Internals
    public int Stamina { get; set; }
    public int Speed { get; set; }
    public int Sharp { get; set; }
    // Special
    public int Dirt { get; set; }
    // Externals
    public int Start { get; set; }
    public int Corner { get; set; }
    public int OutOfTheBox { get; set; }
    public int Competing { get; set; }
    public int Tenacious { get; set; }
    public int Spurt { get; set; }
    //Races
    public virtual ICollection<Race> RaceResults { get; set; }
    //Training
    public virtual ICollection<Training> TrainingResults { get; set; }
}

public class Race
{
    public int RaceId { get; set; }
    public int Favorite { get; set; }
    public LegType LegType { get; set; }
    public int Players { get; set; }
    public DateTime Split { get; set; }
    public DateTime Final { get; set; }
    public int Position { get; set; }

    public virtual int TrackId { get; set; }
    public virtual Track Track { get; set; }

    public virtual int LinkedHorseId { get; set; }
    public virtual Horse LinkedHorse { get;set; }
}

public class Training
{
    public int TrainingId { get; set; }
    public string Type { get; set; }
    public string Result { get; set; }
    public string Food { get; set; }
    public int Start { get; set; }
    public int Corner { get; set; }
    public int Outofthebox { get; set; }
    public int Competing { get; set; }
    public int Tenacious { get; set; }
    public int Spurt { get; set; }

    public virtual int LinkedHorseId { get; set; }
    public virtual Horse LinkedHorse { get; set; }
}

public class Track
{
    public int TrackId { get; set; }
    public string Name { get; set; }
    public int Distance { get; set; }
    public bool G1 { get; set; }
    public int Prize { get; set; }
}

And here is my fluent API code.

public class HorseTracker : DbContext
{
    public DbSet<Horse> Horses { get; set; }
    public DbSet<LegType> LegTypes { get; set; }
    public DbSet<Character> Characters { get; set; }
    public DbSet<Training> TrainingResults { get; set; }
    public DbSet<Track> Tracks { get; set; }
    public DbSet<Race> Races { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Race>()
            .HasRequired(r => r.LinkedHorse)
            .WithMany(h => h.RaceResults)
            .HasForeignKey(r => r.LinkedHorseId);

        modelBuilder.Entity<Training>()
            .HasRequired(t => t.LinkedHorse)
            .WithMany(t => t.TrainingResults)
            .HasForeignKey(t => t.LinkedHorseId);

        modelBuilder.Entity<Race>()
            .HasRequired(r => r.Track)
            .WithMany()
            .HasForeignKey(r => r.TrackId)
            .WillCascadeOnDelete(false);
    }
}

I keep getting this error: Unable to determine the principal end of an association between the types 'DOCCL.Models.Horse' and 'DOCCL.Models.Horse'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

Any clue what i'm doing wrong. I've been playing around with no foreign keys. making one of the required lists optional. they all result in different errors. mostly saying that the relation needs to be a 1:1 relation. And once it said that it had a non nullable field.

I made that nullable int? and then i got the first error again.

I think you need to setup self-referencing relationships manually (specifically, the Horse class properties Sire and Dam are causing an issue).

Try this (in the answer):

What is the syntax for self referencing foreign keys in EF Code First?

You could add two more int IDs representing the foreign keys (SireId, DamId).

If you add this to your model configuration it should work:

modelBuilder.Entity<Horse>()
            .HasRequired(h => h.Dam)    // or HasOptional
            .WithMany();

modelBuilder.Entity<Horse>()
            .HasRequired(h => h.Sire)   // or HasOptional
            .WithMany();

The problem is that the mapping conventions try to create a one-to-one relationship between Dam and Sire and therefore cannot determine what's the principal and what's the dependent because both are optional. Anyway I guess you don't want a one-to-one relationships but actually two one-to-many relationships (the many-side (the "children") not being exposed in the model).

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