patsy2k
patsy2k

Reputation: 611

.NET MVC Entity Framework: one-to-many and many-to-many between the same two tables?

I have a .NET MVC application in which I have created a many-to-many relation between users and companies (those are the companies the user can access).

in user model I added a collection of companies:

public virtual ICollection<Company> companies { get; set; }

and in company model I added a collection of users:

public virtual ICollection<ApplicationUser> users { get; set; }

and added this at OnModelCreating():

    modelBuilder.Entity<ApplicationUser>()
        .HasMany<Company>(s => s.companies)
        .WithMany(c => c.users)
        .Map(cs =>
        {
            cs.MapLeftKey("id_user");
            cs.MapRightKey("id_company");
            cs.ToTable("users_companies");
        });

This is working ok. But now I need to add an FK in users, to add an optional company to the user (to represent the user's company). this relation has nothing to do with the users-companies relation.

so I have added a property in user model:

[ForeignKey("company")]
[Display(Name = "Company")]
public int? Id_company { get; set; }

and a navigation property:

public virtual Company company { get; set; }

and in the company model, I added also a navigation property:

public virtual ApplicationUser user { get; set; }

but when I try to update-database I get this error:

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

after searching for a solution, I tried decorating the user.companies navigation property with:

[InverseProperty("usuarios")]

but this did not solve the error...

(additional info: both models reside in different namespaces, the user is in myApp.Models, the company is in myApp.Models.DAL, but I guess this does not affect the problem...)

Upvotes: 1

Views: 72

Answers (1)

Luiz
Luiz

Reputation: 26

As far as I can see what the message is telling you is that your design is representing a one to one relation and it must be one to many.

In order to do that you must change the company model from:

public virtual ApplicationUser user { get; set; }

To:

public virtual ICollection<ApplicationUser> user { get; set; }

Besides that you will end up with two user collections in your company model.

Like this

public partial class Company
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Company()
        {
            this.User = new HashSet<User>();
            this.User1 = new HashSet<User>();
        }

        public int Id { get; set; }
        public string Name { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<User> User { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<User> User1 { get; set; }
    }

This code was generated by Entity Framework using database first aproach. Using this database model.

I hope this helps.

Upvotes: 1

Related Questions