Ido Ran
Ido Ran

Reputation: 11384

Entity Framework Many to Many Database Migration

I am building ASP MVC web site using Entity Framework 4.4 with .NET Framework 4.0

I've add to my model a many to many relation like so:

  public class User {
    public int UserID { get; set; }
    public string Username { get; set; }
    public virtual ICollection<Tenant> Tenants { get; set; }
  }


  public class Tenant {
    public string TenantID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<User> Users { get; set; }
  }

When I run Add-Migration command I get this migration class (I remove the Down method)

  public partial class TenantUsersManyToManyMigration : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.UserTenants",
                c => new
                    {
                        User_UserID = c.Int(nullable: false),
                        Tenant_TenantID = c.String(nullable: false, maxLength: 128),
                    })
                .PrimaryKey(t => new { t.User_UserID, t.Tenant_TenantID })
                .ForeignKey("dbo.Users", t => t.User_UserID, cascadeDelete: true)
                .ForeignKey("dbo.Tenants", t => t.Tenant_TenantID, cascadeDelete: true)
                .Index(t => t.User_UserID)
                .Index(t => t.Tenant_TenantID);
        }
  }
  1. Why are the field names for TenantID and UserID are User_UserID and Tenant_TenantID and not UserID and TenantID, respectively.

  2. How can I change the default migration scaffolding (or my model) to make cascadeDelete to be false? (currently I simply change it by hand).

Upvotes: 5

Views: 2002

Answers (2)

Mark Oreta
Mark Oreta

Reputation: 10416

You can create your mapping table the way you're wanting using fluent notation. In your DbContext class, override the OnModelCreating with this:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasMany(u => u.Tenants)
            .WithMany(t => t.Users)
            .Map(m =>
                {
                    m.ToTable("UserTenants");
                    m.MapLeftKey("UserId");
                    m.MapRightKey("TenantId");
                });
    }

Also, using fluent, if you want to disable cascade deleting on individual tables, you can use the .WillCascadeDelete(false) when mapping properties. Here's a great post on MSDN on how to use fluent notations.

Upvotes: 7

Joey Gennari
Joey Gennari

Reputation: 2361

You can remove the cascade delete convention this way:

using System.Data.Entity.ModelConfiguration.Conventions;

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}

And then see if the scaffolding changes. I've personally never used it.

Also, Microsoft (kind of) explains the FK naming conventions in this link under the header Foreign Keys.

Upvotes: 4

Related Questions