title: Entity Framework Code First Many-To-Many with shared elements
body: <p>I need to create a many-to-many table relationship in which the elements of one table are shared by the elements of a second table.  I've read the multitude of similar posts, but I'm clearly still wrong somewhere.</p>
  
  <p>I've reduced my problem to this simple example.  I have two tables: Beverages and Ingredients.  I want the Ingredients to be shared among the Beverages.</p>
  
  <p>Is the problem how I've created the bridge table?  (Can I do without a bridge table?)  Or is the problem in how I'm managing the data context?</p>
  
  <p>I have a GetIngredient method with is intended to retrieve a reference to the desired Ingredient.  If no Ingredient exists, a new ingredient is created.</p>
  
  <p>All is as expected until the ctx.SaveChanges() which completes the add of the beverages.  New ingredients are created such that each Beverage has an exclusive list of Ingredients.  This is contrary to my intent.  </p>
  
  <p>Please advise.</p>
  
  <pre><code>  [Fact]
    public void VerifyManyToMany()
    {
       using (var ctx = new CoffeeDbContext())
       {
          // Latte = espresso, steamed milk
          // Macchiato = espresso, milk foam
  
          Beverage beverage1 = new Beverage();
          beverage1.Name = "Latte";
          beverage1.Ingredients.Add( GetIngredient("espresso"));
          beverage1.Ingredients.Add( GetIngredient( "steamed milk"));
          ctx.Beverages.Add(beverage1);
  
          Beverage beverage2 = new Beverage();
          beverage2.Name = "Macchiato";
          beverage2.Ingredients.Add(GetIngredient("espresso"));
          beverage2.Ingredients.Add(GetIngredient("milk foam"));
          ctx.Beverages.Add(beverage2);
  
          // prior to this line, Ingredient table comprised of:
          //    {"espresso", "steamed milk", "milk foam"}
          ctx.SaveChanges();
  
          // after this line, Ingredient table comprised of:
          //    {"espresso", "steamed milk", "milk foam", "espresso", "espresso", "steamed milk", "milk foam"}
  
          List&lt;Ingredient&gt; ingredientList = ctx.Ingredients.ToList();
  
          Assert.True( ingredientList.Count == 2);
       }
  
    }
  
    /// &lt;summary&gt;
    /// Retrieve ingredient of designated name.
    /// If no ingredient exists, create new ingredient.
    /// &lt;/summary&gt;
    /// &lt;param name="name"&gt;&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    private Ingredient GetIngredient(string name)
    {
       using (var ctx = new CoffeeDbContext())
       {
          Ingredient ingredient = ctx.Ingredients.SingleOrDefault(i =&gt; i.Name == name);
  
          if (ingredient == null)
          {
             ingredient = new Ingredient { Name = name };
             ctx.Ingredients.Add(ingredient);
             ctx.SaveChanges();
          }
          return ingredient;
       }
    }
  </code></pre>
  
  <p>Beverage Class</p>
  
  <pre><code>public class Beverage
  {
     public Beverage()
     {
        this.Ingredients = new HashSet&lt;Ingredient&gt;();
     }
  
     [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     public virtual int BeverageId { get; set; }
  
     public virtual string Name { get; set; }
  
     // many-to-many relationship, every Beverage comprised meany ingredients
     public virtual ICollection&lt;Ingredient&gt; Ingredients { get; private set; }
  }
  </code></pre>
  
  <p>Ingredient Class</p>
  
  <pre><code>public class Ingredient
  {
    public Ingredient()
    {
       this.Beverages = new List&lt;Beverage&gt;();
    }
  
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual int IngredientId { get; set; }
  
    public virtual string Name { get; set; }
  
    // many-to-many relationship, Ingredient used by many Beverages
    public ICollection&lt;Beverage&gt; Beverages { get; private set; } 
  }
  </code></pre>
  
  <p>DbContext</p>
  
  <pre><code>public class CoffeeDbContext : DbContext
  {
     public DbSet&lt;Beverage&gt; Beverages { get; set; } 
     public DbSet&lt;Ingredient&gt; Ingredients { get; set; }
  
     protected override void OnModelCreating(DbModelBuilder modelBuilder)
     {
        modelBuilder.Entity&lt;Beverage&gt;()
           .HasMany(x =&gt; x.Ingredients)
           .WithMany(x =&gt; x.Beverages)
           .Map(
              m =&gt;
              {
                 m.MapLeftKey("BeverageId");
                 m.MapRightKey("IngredientId");
                 m.ToTable("BeverageIngredients");
              }
           );
     }
  }
  </code></pre>