none
MVC - Eager Loading and OnModelCreating RRS feed

  • Question

  • I have these Models in my MVC project:

      

    public class Category { [Key] public int CategoryIdgetset; } [Required(ErrorMessage="Category name is required.")] public string Name { getset; } public bool Visible { getset; } public int Index { getset; } public ICollection<Product>Products { getset; } }

    	public class Product
    	{
     
    		[Key]
    		[DatabaseGenerated(DatabaseGeneratedOption.None)]
    		[Display(Name = "Product Number")]
    		public int ProductId { getset; }
    		public string Name { getset; }
    		public int AmountInStock { getset; }
    		public bool Available { getset; }
     
    		[Display(Name = "Category")]
    		public int? CategoryId { getset; }
    		public virtual  Category Category { getset; }
    	
     
    	}

               Then I have the ViewResult in the ProductsController:

          public ViewResult Index()
            {
                var courses = db.Courses.Include(c => c.Department);
                return View(courses.ToList());
            }

    This works fine and all the category is being loaded when I am showing the products.

    Now - I want to be able to delete a category from the Category model. I cannot because there are dependencies to the Products model.

    Therefore I add an OnModelCreating to my WebShopContext

    	public class WebShopContext : DbContext
    	{
    		public DbSet<Category> Categories { getset; }
     
    		public DbSet<Product> Products { getset; }
     
    		protected override void OnModelCreating(DbModelBuilder modelBuilder)
    		{
    			modelBuilder.Entity<Category>()
    				.HasOptional(p=> p.Products)
    				.WithOptionalDependent()
    				.WillCascadeOnDelete(true);
    		}
     
    	}

    Now I am able to delete the Categories from the Category Model. But now - the Category will not load with the Product - when those are being loaded.

    Any suggestions?

    • Moved by Mike Dos Zhang Tuesday, March 20, 2012 2:42 AM (From:Windows Forms Data Controls and Databinding)
    Monday, March 19, 2012 3:04 PM

Answers

  • Hi Jesper,

    Please try my code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity;
    
    namespace Delete
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (var db= new MyContext())
                {
                    //db.Database.CreateIfNotExists();
                    //var c1 = new Category { CategoryId = 1, Name = "category1", Index = 1, Visible = true, Products = new List<Product>() };
                    //var p1 = new Product { ProductId = 1, Name = "product1", Available = true, AmountInStock = 1 };
                    //var p2 = new Product { ProductId = 2, Name = "product2", Available = true, AmountInStock = 2 };
                    //var p3 = new Product { ProductId = 3, Name = "product3", Available = true, AmountInStock = 3 };
                    //c1.Products.Add(p1);
                    //c1.Products.Add(p2);
                    //c1.Products.Add(p3);
                    //db.Categories.Add(c1);
                    //db.SaveChanges();
                    var c1 = db.Categories.Include("Products").First();
                    c1.Products.Clear();
                    db.Categories.Remove(c1);
                    db.SaveChanges();
                   
                }
            }
        }
        public class Category
        {
            [Key]
            public int CategoryId { get; set; }      
            public string Name { get; set; }
            public bool Visible { get; set; }
            public int Index { get; set; }
            public virtual ICollection<Product> Products { get; set; }
        }
        public class Product
        {
            [Key]
            [DatabaseGenerated(DatabaseGeneratedOption.None)]
            public int ProductId { get; set; }
            public string Name { get; set; }
            public int AmountInStock { get; set; }
            public bool Available { get; set; }
            public int? CategoryId { get; set; }
            [ForeignKey("CategoryId")]
            public virtual Category Category { get; set; }
        }
        public class MyContext:DbContext
        {
            public DbSet<Category> Categories { get; set; }
            public DbSet<Product> Products { get; set; }
          
        }
    }
    

    Have a nice day.

    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, March 22, 2012 9:17 AM
    Moderator

All replies

  • Hi SirLanceLang,

    Welcome!

    According to your description, There are navigations in your classes, you should use Fluent API like this:

    modelBuilder.Entity<Category>() 
        .HasMany(c => c.Products) 
        .WithRequired(p => p.PrimaryCategory) 
        .HasForeignKey(p => p.PrimaryCategoryCode) 
        .WillCascadeOnDelete(false);

    For MVC application with EF, here is a good vedio: http://msdn.microsoft.com/en-us/data/gg715119

    For Eager loading, you can refer here: http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx using "Include" key word.

    Have a nice day.

     

    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, March 20, 2012 6:42 AM
    Moderator
  • Hi Alan,

    Thanks for your reply. I already tried using your suggestion. Though I put "True" instead of false on the cascade. This though will result in deleting all the products as well for a given category when deleting the category.

    I only want the category to be deleted and when deleting the category the category property in the productsClass should be set to null.

    With the above code inserted (cascade set to False) and trying to delete a Category will result in this error:

    {"The primary key value cannot be deleted because references to this key still exist. [ Foreign key constraint name = Category_Products ]"}

    Best regards

    Jesper Bolling


    Jesper Bolling

    Tuesday, March 20, 2012 1:59 PM
  • Hi Jesper,

    Please try my code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity;
    
    namespace Delete
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (var db= new MyContext())
                {
                    //db.Database.CreateIfNotExists();
                    //var c1 = new Category { CategoryId = 1, Name = "category1", Index = 1, Visible = true, Products = new List<Product>() };
                    //var p1 = new Product { ProductId = 1, Name = "product1", Available = true, AmountInStock = 1 };
                    //var p2 = new Product { ProductId = 2, Name = "product2", Available = true, AmountInStock = 2 };
                    //var p3 = new Product { ProductId = 3, Name = "product3", Available = true, AmountInStock = 3 };
                    //c1.Products.Add(p1);
                    //c1.Products.Add(p2);
                    //c1.Products.Add(p3);
                    //db.Categories.Add(c1);
                    //db.SaveChanges();
                    var c1 = db.Categories.Include("Products").First();
                    c1.Products.Clear();
                    db.Categories.Remove(c1);
                    db.SaveChanges();
                   
                }
            }
        }
        public class Category
        {
            [Key]
            public int CategoryId { get; set; }      
            public string Name { get; set; }
            public bool Visible { get; set; }
            public int Index { get; set; }
            public virtual ICollection<Product> Products { get; set; }
        }
        public class Product
        {
            [Key]
            [DatabaseGenerated(DatabaseGeneratedOption.None)]
            public int ProductId { get; set; }
            public string Name { get; set; }
            public int AmountInStock { get; set; }
            public bool Available { get; set; }
            public int? CategoryId { get; set; }
            [ForeignKey("CategoryId")]
            public virtual Category Category { get; set; }
        }
        public class MyContext:DbContext
        {
            public DbSet<Category> Categories { get; set; }
            public DbSet<Product> Products { get; set; }
          
        }
    }
    

    Have a nice day.

    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, March 22, 2012 9:17 AM
    Moderator
  • Hi,

    I am writing to check the status of the issue on your side. Would you mind letting us know the result of the suggestions?
    If you need further assistance, please feel free to let me know. I will be more than happy to be of assistance.
    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, March 26, 2012 8:12 AM
    Moderator