5

I'm trying to do this with EF Code First:

database model

There area two tables: Users and Areas. One User belongs to one required area and one Area can have zero or one User (as administrator). Then:

Users *..1 Areas and Users 0..1 Areas

The Users class:

public class User {
    public int UserId { get; set; }
    public string Name { get; set; }

    [ForeignKey("Area")]
    public int AreaId { get; set; }
    [InverseProperty("Users")]
    public virtual Area Area { get; set; }

    public virtual Area AreaTitular { get; set; }
}

The Areas class:

public class Area {
    public int AreaId { get; set; }
    public string Name { get; set; }

    public List<User> Users { get; set; }

    [ForeignKey("User")]
    public int? UserId { get; set; }
    [InverseProperty("AreaTitular")]
    public virtual User User{ get; set; }
}

And the error on update-database command:

Unable to determine the principal end of an association between the types 'TestEntityFrameworkCodeFirst.Model.Area' and 'TestEntityFrameworkCodeFirst.Model.User'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

Any help will be very appreciated :)

I'm not completely sure if this is ok:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
    modelBuilder.Entity<Area>()
        .HasOptional(i => i.User)
        .WithOptionalDependent();
    base.OnModelCreating(modelBuilder);
}

Just added this on the OnModelCreating on the Context class. And this is how it looks in SQL Server:

Database

Mr. DMX
  • 653
  • 2
  • 9
  • 20
  • Entity Framework doesn't know which one of these is the 1 and which is the 0 end. It tells you what to do in the error. But why do you have two `Area` navigation properties? – Claies Feb 09 '15 at 22:18
  • Duplicate of http://stackoverflow.com/questions/6531671/what-does-principal-end-of-an-association-means-in-11-relationship-in-entity-fr – ChrisV Feb 09 '15 at 22:29
  • @Claies User.Area goes to Area.Usuarios and User.AreaTitular goes to Area.Usuario.. Is this wrong? – Mr. DMX Feb 10 '15 at 01:41
  • @ChrisV My question is about having two relations on two classes.. the other is about 1..1 relationship right? – Mr. DMX Feb 10 '15 at 01:46
  • I'm still not sure I understand what you are trying to do. You want to have 2 different relationships with the same classes? – Claies Feb 10 '15 at 01:51
  • Ok, this is the idea: a User works in an Area so I need the AreaId in the User class to retrieve the Area data... and an Area has a manager wich is a User and I need the UserId to know which User is the admin and get its data. Should I just use a simple UserId in my Area class without all that relationship stuff? – Mr. DMX Feb 10 '15 at 02:25
  • I'm trying to do something like this: http://stackoverflow.com/questions/14542763/2-relationships-between-2-entities-in-er-diagram or this: http://stackoverflow.com/questions/8583194/multiple-relationships-between-two-entities-is-this-good-practice – Mr. DMX Feb 10 '15 at 02:31

1 Answers1

3

The problem is in the configuration of your one-to-one relationship because one end must be principal and second end must be dependent. When you are configuring this kind of relationship, Entity Framework requires that the primary key of the dependent also be the foreign key.So, don't map UsuarioId as FK, otherwise, EF requires that FK must be PK too (comment that property). The other problem is EF doesn't know who is the principal in your relationship. To especify who is the principal, use the Required attribute. If you, for example, add this attribute over AreaTitular, you are specifying that to create a User, the AreaTitular property must be set it after save changes, so your principal in this case is Area and the dependend is User, but this is hypothetical escenario, I don't know your logic. Check this posts for more info:

Now, it's possible especify both ends as optional, but one of them must be principal. If this is your case, I suggest you comment the Data Annotations attributes and configure the relationships using Fluent Api this way:

   protected override void OnModelCreating(DbModelBuilder modelBuilder)
   {
        modelBuilder.Entity<User>()
            .HasRequired(a => a.Area)
            .WithMany(c => c.Usuarios)
            .HasForeignKey(a => a.AreaId);

        modelBuilder.Entity<Area>()
            .HasOptional(a => a.Usuario)
            .WithOptionalPrincipal(u => u.AreaTitular);
   }

I suggest you read this page to understand better the one-to-one relationships.

Community
  • 1
  • 1
ocuenca
  • 38,548
  • 11
  • 89
  • 102
  • Thanks! I was reading that book and the section about one to one relationship, the problem I found was about having two relationships on two entities and how to configure them. Finally, maybe the best way is avoid this kind of issues and use other table to handle this kind on relationship, don't you think? – Mr. DMX Feb 10 '15 at 04:49
  • With your fluent api solution the tables look like this: Areas [AreaId(PK, int, not null), Name] Users [UserId(PK, int, not null), Name, AreaId(FK, int, not null), AreaTitular_AreaId(FK, int, null)] I think this solves the problem! – Mr. DMX Feb 10 '15 at 06:13
  • Happy for you my friend ;), the first FK is related with the one-to-many relationship (AreaId) and the second one ( AreaTitular_AreaId) is related to the one-to-one. – ocuenca Feb 10 '15 at 14:13