Home > OS >  Asp net core api post request with many to many controller
Asp net core api post request with many to many controller

Time:09-25

I have simple question. I have 2 models, coctails and ingredients:

    public class Coctails
{
    [Required]
    public long CoctailsId { get; set; }

    public string Name { get; set; }

    public string CookingMethod { get; set; }

    public double Price { get; set; }

    public List<Ingredients> CoctailIngredients { get; set; }
}

    public class Ingredients
{

    [Required]
    public long IngredientsId { get; set; }

    
    public string Name { get; set; }

    public double Amount { get; set; }

    public double Price { get; set; }

    public List<Coctails> CoctailsWithThisIngredient { get; set; }
}

I am saving 1 ingredient using postman with following request:

{
"Name":"vodka",
"Amount":1000,
"Price":100}

After that I am trying to add new coctail with post request:

{
"Name":"vodka s pivom" ,
"CookingMethod":"rubilovo",
"Price":100,
"coctailIngredients":
[
    {
        "Name" : "vodka",
        "Amount" : 50
    }
]}

And I have error with endless loop (but I need those 2 fields CoctailIngredients and CoctailsWithThisIngredient to tell ef that this is many to many relations and it is making 3rd connection table for me)...so how to avoid such situation?

My db context class:

    public class DatabaseContext : DbContext
{
    public DatabaseContext()
    {
    }

    public DbSet<Coctails> Coctails { get; set; }
    public DbSet<Ingredients> Ingredients { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Coctails>()
                .HasMany(c => c.CoctailIngredients)
                .WithMany(s => s.CoctailsWithThisIngredient)
                .UsingEntity(j => j.ToTable("CoctailsWithIngredients"));
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Filename=BarDb.db");
    }


}

My POST method:

    [HttpPost]
    public async Task<ActionResult<Coctails>> PostCoctails(Coctails coctails)
    {
        _context.Coctails.Attach(coctails);

        await _context.SaveChangesAsync();

        return CreatedAtAction("GetCoctails", new { id = coctails.CoctailsId }, coctails);
    }

CodePudding user response:

The only way to keep many-to-many relations is to add the third table. If you use Ef core 5 , ef can create this table for you in shadow, but it is always better to create it explicitly:

public class CoctailIngridient
{
     [Key]
    public long Id { get; set; }

    public long CoctailId { get; set; }
    public long IngredientId { get; set; }
    public virtual Coctail Coctail { get; set; }
    public virtual Ingredient Ingridient { get; set; }
 }

public class Coctail
{
    [Key]
    public long CoctailsId { get; set; }

    public string Name { get; set; }

    public string CookingMethod { get; set; }

    public double Price { get; set; }

    public List<CoctailIngredient> CoctailIngredients { get; set; }

    //only for ef core 5 
    public List<Ingredient> Ingredients { get; set; }
 }

 public class Ingredient
{

    [Key]
    public long IngredientId { get; set; }

    
    public string Name { get; set; }

    public double Amount { get; set; }

    public double Price { get; set; }

     public List<CoctailIngredient> CoctailIngredients { get; set; }

     //only for ef core 5 
    public List<Coctail> Coctails { get; set; }
}

CodePudding user response:

Adding third model class and removing OnModelCreating method from Database context method did the trick. I guess problem is solved. Thanks for help!

And one more really important thing, I've also have added 'NotMapped' tag above my

public List<Coctails> CoctailsWithThisIngredient { get; set; }

and

public List<Ingredients> CoctailIngredients { get; set; }
  • Related