1 Replies - 921 Views - Last Post: 12 October 2015 - 05:23 AM

#1 ScottinTexas   User is offline

  • D.I.C Regular

Reputation: 12
  • View blog
  • Posts: 312
  • Joined: 13-March 12

How to Set Up Related Data in Model

Posted 22 March 2015 - 05:48 AM

I'm still trying to come to grips with related data access when I set up my models.
I have a table of recipes, each recipe is related to a list of ingredients. This is a simple one to many relationship.
Also each recipe can belong to one or many Categories.

Recipe Class
	public class Recipe
	{
		public int RecipeID { get; set; } 

		public string PhotoPath { get; set; } //Got a photo? Include it. Path to photo i.e /Photos/1234567.jpg
		public string Title { get; set; } //i.e Coq au van
		public string Author { get; set; }	//Me or whoever I got it from
		public string Description { get; set; } //i.e. "Super easy and cheesy comfort food for winter."

		[DataType(DataType.Time)]
		[DisplayFormat(DataFormatString = "{0:t}", ApplyFormatInEditMode = true)]
		public DateTime PrepTime { get; set; } //2 days, 6 hours, 23 minutes

		[DataType(DataType.Time)]
		[DisplayFormat(DataFormatString = "{0:t}", ApplyFormatInEditMode = true)]
		public DateTime CookTime { get; set; } //6 hours

		public int Servings { get; set; } //6
		public string ServingSize { get; set; } //12oz
		public float CaloriesPerServing { get; set;}

		[DataType(DataType.Date)]
		[DisplayFormat(DataFormatString="{0:d}", ApplyFormatInEditMode=true)]
		public DateTime DateAdded { get; set; }
		public string Directions { get; set; }

//Foreign Keys
public int CategoryID { get; set; }
public int IngredientID { get; set; }

//Navigation Properties
public virtual List<RecipeCategory> Categories { get; set; }
public virtual List<Ingredient> Ingredients { get; set; }

}



Category Class
	public class RecipeCategory
	{
		/* A user can type a Category or choose from a list of previously defined categories such as "Chicken", "Pasta", "Salad", etc.
		 */
		public int RecipeCategoryID { get; set; }
		public string Description { get; set; }
		public int RecipeID { get; set; }
	}



And finally the Ingredients Class
	public class Ingredient
	{
		/* 1/4 cup turmeric 
		 2 medium onions chopped*/

		public int IngredientID { get; set; }
		public string Description { get; set; }
		public int RecipeID { get; set; }
	}



My RecipeContext class has the obligatory DBSets for each of these tables.
	public class RecipeContext : DbContext
	{
		public RecipeContext() : base("RecipeContext") { }
		public DbSet<Recipe> Recipes { get; set;}
		public DbSet<Ingredient> Ingredients { get; set; }
		public DbSet<RecipeCategory> Catagories { get; set; }

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

	}



When I get a recipe I should get the Name of the Category and not the ID (as I do now because the ID is in the recipe table). What I want is the Related Name i.e ID=1, Name=Pasta. I should get a list of related ingredients where RecipeID =1 and any ingredients in the ingredients table with that ID should be in a list. Following examples (primarily the Contoso University tutorial) almost addresses the question, but I got confused because there seems to be a "jump over" in the details.
As I understand it;
When I create an instance of recipe it should load all of recipes (based on the DB context) load all of the ingredients and all of the categories since I don't see anywhere that the ingredients are being filtered in any way. All of the categories is fine. What am I missing?

Is This A Good Question/Topic? 0
  • +

Replies To: How to Set Up Related Data in Model

#2 IngeniousHax   User is offline

  • |>|20-514<|{3|2

Reputation: 84
  • View blog
  • Posts: 1,385
  • Joined: 28-March 09

Re: How to Set Up Related Data in Model

Posted 12 October 2015 - 05:23 AM

Even though this is old, I am replying to it as it may help someone else down the road.

I would use Fluent API to configure the relationships in the RecipeContext file:

// One-to-many relationship with recipe being required before we can add Ingredient and RecipeCategory
modelBuilder.Entity<Ingredient>().HasRequired(x => x.Recipe).WithMany(x => x.Ingredient).HasForeignKey(x => x.RecipeForeignKey);
modelBuilder.Entity<RecipeCategory>().HasRequired(x => x.Recipe).WithMany(x => x.RecipeCategory).HasForeignKey(x => x.RecipeForeignKey);



Also, complete the Navigation Properties in the Models, and use ICollection<> instead of List<>:

// Recipe.cs
public virtual ICollection<RecipeCategories> recipeCategories { get; set; }
public virtual ICollection<Ingredient> ingredients { get; set; }

// RecipeCategory.cs
public virtual Recipe recipe { get; set; }

// Ingredient.cs
public virtual Recipe recipe { get; set;}



And in order to get the related information from the tables that you want (if I'm reading this correctly), in a controller you could perform some query like the following:

var recipes = db.recipe.Where(x => x.id == selectedRecipeID).ToList();

// If you only want the ingredients pertaining to a recipe... I think this would work
var ingredients = db.recipe.Where(x => x.id == selectedRecipeID).ingredients.FirstOrDefault();




And in the View, simply iterate over the required items

foreach(var x in Model.RecipeCategory)
{
    // print the recipe categories
    foreach(var x in Model.Ingredients)
    {
       // Print the ingredients to each recipe category
    }
}



Of course this is just a general approach and could be refined a bit, however, it should work. I think I might have gotten the relationships between RecipeCategory and Recipe reversed, however, from what is shown it looks like this is attempting to make a 1-* from Recipe->(RecipeCategory || Ingredients)...

This post has been edited by IngeniousHax: 12 October 2015 - 05:25 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1