Many to many relationship in Entity Framework Code First 6

asp.net-mvc-4 code-first entity-framework-6

Question

I have a problem in EF 6 Code First while I am doing many to many relationship approaches. It will not populate my Tags and Posts list.

What I am trying to do:

Post

public class Post
{
    public int PostID { get; set; }

    public string Title { get; set; }
    public string Description { get; set; }

    public virtual Category Category { get; set; }
    public int CategoryID { get; set; }

    public virtual ICollection<Tag> Tags { get; set; }
}

Category

public class Category
{
    public int CategoryID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

Tag

public class Tag
{
    public int TagID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

PostTagMap

public class PostTagMap
{
    public virtual Post Post { get; set; }
    [Key, Column(Order = 0)]
    public int PostID { get; set; }

    public virtual Tag Tag { get; set; }
    [Key, Column(Order = 1)]
    public int TagID { get; set; }
}

PostDbContext

public class PostDbContext : DbContext
{
    public PostDbContext()
    {
        Database.SetInitializer(new PostDbContextInitializer());
    }

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

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Post> Post { get; set; }
    public DbSet<Tag> Tag { get; set; }
    public DbSet<Category> Category { get; set; }

    public DbSet<PostTagMap> PostTagMap { get; set; }
}

PostDbContextInitializer

public class PostDbContextInitializer : DropCreateDatabaseIfModelChanges<PostDbContext>
{
    protected override void Seed(PostDbContext context)
    {
        List<Category> listCategory = new List<Category>
        {
            new Category { Name = "Programming" },
            new Category { Name = "Designing" },
            new Category { Name = "Database" },
        };

        List<Tag> listTag = new List<Tag>
        {
            new Tag { Name = "Csharp" },
            new Tag { Name = "Asp.Net" },
            new Tag { Name = "Sencha Touch" },
            new Tag { Name = "MVC" },
            new Tag { Name = "SqlServer" },
            new Tag { Name = "Oracle" },
            new Tag { Name = "Bootstrap" },
            new Tag { Name = "Jquery" },
        };

        List<Post> listPost = new List<Post>
        {
            new Post { Title = "List Paging in Sencha Touch", Description = "In this one I am going to add one more important and most used functionality i.e. paging in sencha touch List.", Category = listCategory.Find(m => m.Name.Equals("Programming")) },
            new Post { Title = "CRUD Operation using Sencha Touch and ASP.Net MVC Web API", Description = "CRUD Operation using Sencha Touch and ASP.Net MVC Web API In this article I am going to explain and demonstrate how to create", Category = listCategory.Find(m => m.Name.Equals("Programming")) },
            new Post { Title = "Union Example in SQL Server", Description = "In this article I am going to explain a use of union operator in SQL Server Database with a real life scenario and example. The UNION operator is used to combine the result-set of two or more SELECT statements.", Category = listCategory.Find(m => m.Name.Equals("Database")) },
            new Post { Title = "Pivot with Dynamic columns in SQL Server", Description = "Pivot with Dynamic columns in SQL Server In this article I will present how we can write a Dynamic PIVOT.", Category = listCategory.Find(m => m.Name.Equals("Database")) },
        };

        List<PostTagMap> listPostTagMap = new List<PostTagMap>
        {
            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("List Paging in Sencha Touch")), Tag = listTag.Find(m => m.Name.Equals("Sencha Touch")) },
            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("List Paging in Sencha Touch")), Tag = listTag.Find(m => m.Name.Equals("Asp.Net")) },

            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("CRUD Operation using Sencha Touch and ASP.Net MVC Web API")), Tag = listTag.Find(m => m.Name.Equals("Sencha Touch")) },
            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("CRUD Operation using Sencha Touch and ASP.Net MVC Web API")), Tag = listTag.Find(m => m.Name.Equals("Asp.Net")) },
            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("CRUD Operation using Sencha Touch and ASP.Net MVC Web API")), Tag = listTag.Find(m => m.Name.Equals("MVC")) },
            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("CRUD Operation using Sencha Touch and ASP.Net MVC Web API")), Tag = listTag.Find(m => m.Name.Equals("Csharp")) },

            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("Union Example in SQL Server")), Tag = listTag.Find(m => m.Name.Equals("SqlServer")) },
            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("Union Example in SQL Server")), Tag = listTag.Find(m => m.Name.Equals("Oracle")) },

            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("Pivot with Dynamic columns in SQL Server")), Tag = listTag.Find(m => m.Name.Equals("Oracle")) },
            new PostTagMap { Post = listPost.Find(m => m.Title.Equals("Pivot with Dynamic columns in SQL Server")), Tag = listTag.Find(m => m.Name.Equals("SqlServer")) },
        };

        listCategory.ForEach(m =>
        {
            context.Category.Add(m);
        });
        context.SaveChanges();

        listTag.ForEach(m =>
        {
            context.Tag.Add(m);
        });
        context.SaveChanges();

        listPost.ForEach(m =>
        {
            context.Post.Add(m);
        });
        context.SaveChanges();

        listPostTagMap.ForEach(m =>
        {
            context.PostTagMap.Add(m);
        });
        context.SaveChanges();

        base.Seed(context);
    }
}

The above everything is working fine and database entry would also be correct. But the problem is occurring when I am trying retrieving a result set in Controller. It will not populating Tags list in Post and Posts list in Tag.

public class HomeController : Controller
{
    PostDbContext db = new PostDbContext();

    public ActionResult Index()
    {
        //var posts = db.Post.ToList();

        var posts = db.Post.Include(m => m.Tags).ToList();
        var tags = db.Tag.ToList();
        var categories = db.Category.ToList();

        return View(posts);
    }
}

Please help me. How can I achieve this?

1
1
5/9/2014 8:22:10 AM

Accepted Answer

You do not need to create PostTagMap table explicitly. Entity framework will create the join table for you and as you are using Navigation properties (ICollection, etc.). Try addings a List of tags directly to one of your posts in the Seed method. This should then show up in your Index view.

Code:

public class Post
{
    public int PostID { get; set; }

    public string Title { get; set; }
    public string Description { get; set; }

    public virtual Category Category { get; set; }
    public int CategoryID { get; set; }

    public virtual ICollection<Tag> Tags { get; set; }
}

public class Category
{
    public int CategoryID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

public class Tag
{
    public int TagID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

public class PostDbContext : DbContext
{
    public PostDbContext()
    {
        Database.SetInitializer(new PostDbContextInitializer());
    }

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

        modelBuilder.Entity<Post>().HasMany<Tag>(s => s.Tags).WithMany(c => c.Posts).Map(m =>
        {
            m.MapLeftKey("PostID");
            m.MapRightKey("TagID");
            m.ToTable("PostTagMap");
        });

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Post> Post { get; set; }
    public DbSet<Tag> Tag { get; set; }
    public DbSet<Category> Category { get; set; }
}

public class PostDbContextInitializer : DropCreateDatabaseIfModelChanges<PostDbContext>
{
    protected override void Seed(PostDbContext context)
    {
        List<Category> listCategory = new List<Category>
        {
            new Category { Name = "Programming" },
            new Category { Name = "Designing" },
            new Category { Name = "Database" },
        };

        List<Tag> listTag = new List<Tag>
        {
            new Tag { Name = "Csharp" },
            new Tag { Name = "Asp.Net" },
            new Tag { Name = "Sencha Touch" },
            new Tag { Name = "MVC" },
            new Tag { Name = "SqlServer" },
            new Tag { Name = "Oracle" },
            new Tag { Name = "Bootstrap" },
            new Tag { Name = "Jquery" },
        };

        List<Post> listPost = new List<Post>
        {
            new Post { Title = "List Paging in Sencha Touch", Description = "In this one I am going to add one more important and most used functionality i.e. paging in sencha touch List.", Category = listCategory.Find(m => m.Name.Equals("Programming")), Tags = listTag.Where(x => x.Name.Equals("Sencha Touch") || x.Name.Equals("Asp.Net")).ToList() },
            new Post { Title = "CRUD Operation using Sencha Touch and ASP.Net MVC Web API", Description = "CRUD Operation using Sencha Touch and ASP.Net MVC Web API In this article I am going to explain and demonstrate how to create", Category = listCategory.Find(m => m.Name.Equals("Programming")) },
            new Post { Title = "Union Example in SQL Server", Description = "In this article I am going to explain a use of union operator in SQL Server Database with a real life scenario and example. The UNION operator is used to combine the result-set of two or more SELECT statements.", Category = listCategory.Find(m => m.Name.Equals("Database")) },
            new Post { Title = "Pivot with Dynamic columns in SQL Server", Description = "Pivot with Dynamic columns in SQL Server In this article I will present how we can write a Dynamic PIVOT.", Category = listCategory.Find(m => m.Name.Equals("Database")) },
        };

        listCategory.ForEach(m =>
        {
            context.Category.Add(m);
        });
        context.SaveChanges();

        listTag.ForEach(m =>
        {
            context.Tag.Add(m);
        });
        context.SaveChanges();

        listPost.ForEach(m =>
        {
            context.Post.Add(m);
        });
        context.SaveChanges();

        base.Seed(context);
    }
}
1
5/10/2014 9:49:24 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow