2016-10-08 1 views
0

Je suis encore en train d'apprendre framework d'entité avec MVC et en essayant de créer un site d'achat générique. J'ai des modèles - Catégorie et Produits ayant une relation un-à-plusieurs (par exemple: Produit "IPhone7" appartiendra à la catégorie "Électronique") See Models edmx diagram hereEntity Framework ajoute un enregistrement inutile sur SaveChanges()

Le problème est quand j'ajoute un nouveau produit, disons P, appartenant à catégorie C, EF ajoute automatiquement une nouvelle entrée C à la table Catégorie, même si C existe déjà dans la table Catégorie. Je crois que la question est la façon dont EF gère les relations un-à-plusieurs. J'ai également essayé d'ajouter [Index (IsUnique = true)] à categoryName dans la classe Category, mais cela n'a pas aidé. Je ne veux pas qu'EF ajoute une nouvelle catégorie chaque fois qu'un produit est ajouté. Ci-dessous l'extrait de code de mon contrôleur, vue, couche de données et couche de gestion.

//Controller 
    public ActionResult SaveCategory(Category c) 
    { 
     AdminBusinessLayer adminBL = new AdminBusinessLayer(); 
     adminBL.AddCategory(c); 
     return RedirectToAction("Index"); 
    } 

    public ActionResult SaveProduct(Product p, string btnSubmit, string dpdCategories) 
    { 
     AdminBusinessLayer adminBL = new AdminBusinessLayer(); 
     Category productCategory = new Category(); 
     List<Category> categoryList = new List<Category>(); 
     categoryList = adminBL.ShowCategory(); 
     foreach (Category c in categoryList) 
     { 
      if (c.CategoryName == dpdCategories) 
       productCategory = c; 
     } 
     p.category = productCategory; 
     p.CategoryId = productCategory.Id; 
     adminBL.AddProduct(p); 
     return RedirectToAction("Index"); 
    } 

@{ 
 
    ViewBag.Title = "Admin Functions"; 
 
} 
 

 
@using Flipkart.ViewModels 
 
@using Flipkart.Models 
 
@model AdminViewModel 
 

 
<form action="/Admin/SaveCategory" method="post"> 
 
    <h2>Add New Category</h2> 
 
    Name: <input type="text" id="txtCategoryName" name="CategoryName" /> 
 
    <br /> 
 
    <br /> 
 
    <input type="submit" name="btnAddCategory" value="Add Category" /> 
 
    <br /> 
 
    <br /> 
 
    <h2>Existing Categories</h2> 
 
    <table border="1" cellpadding="5" width="20"> 
 
     <tr style="background-color:yellowgreen"> 
 
      <th>Id</th> 
 
      <th>Category</th> 
 
     </tr> 
 
     @foreach (Category c in Model.categoryList) 
 
     { 
 
      <tr> 
 
       <td>@c.Id</td> 
 
       <td>@c.CategoryName</td> 
 
      </tr> 
 
     } 
 
    </table> 
 
</form> 
 
<br /> 
 
<br /> 
 
<br /> 
 
<br /> 
 
<form action="/Admin/SaveProduct" method="post"> 
 
    <h2>Add New Product</h2> 
 
    Name: <input type="text" id="txtProductName" name="ProductName" /> 
 
    Category: @Html.DropDownList("dpdCategories",new SelectList(Model.categoryNames,Model)) 
 
    Price: @Html.TextBox("Price") 
 
    <br /> 
 
    <br /> 
 
    <input type="submit" name="btnAddProduct" value="Add Product" /> 
 
    <br /> 
 
    <br /> 
 
    <br /> 
 
    <br /> 
 
    <h2>Existing Products</h2> 
 
    <table border="1" cellpadding="5" width="20"> 
 
     <tr style="background-color:yellowgreen"> 
 
      <th>Id</th> 
 
      <th>Product</th> 
 
     </tr> 
 
     @foreach (Product p in Model.productList) 
 
     { 
 
      <tr> 
 
       <td>@p.Id</td> 
 
       <td>@p.ProductName</td> 
 
      </tr> 
 
     } 
 
    </table> 
 
</form>

//Data Layer 
public class FlipkartContext:DbContext 
{ 
    public FlipkartContext() : base("Flipkart") 
    { 
    } 
    public DbSet<Category> Category { get; set; } 
    public DbSet<Product> Product { get; set; } 
    public DbSet<Cart> cart { get; set; } 
} 

est inférieure à la couche d'affaires qui enregistre les données à la base de données:

//Business Layer 
    public void AddCategory(Category c) 
    { 
     FlipkartContext flipkartDBContext = new FlipkartContext(); 
     flipkartDBContext.Category.Add(c); 
     flipkartDBContext.SaveChanges(); 
    } 

    public List<Category> ShowCategory() 
    { 
     List<Category> categoryList = new List<Category>(); 
     FlipkartContext flipkartDBContext = new FlipkartContext(); 
     categoryList = flipkartDBContext.Category.ToList(); 
     return categoryList; 
    } 
    public void AddProduct(Product p) 
    { 
     FlipkartContext flipkartDBContext = new FlipkartContext(); 
     flipkartDBContext.Product.Add(p); 
     flipkartDBContext.SaveChanges(); 
    } 

    public List<Product> ShowProduct() 
    { 
     List<Product> productList = new List<Product>(); 
     FlipkartContext flipkartDBContext = new FlipkartContext(); 
     productList = flipkartDBContext.Product.ToList(); 
     return productList; 
    } 
+0

Pouvez-vous également ajouter un code de classe de produit? – Sefa

Répondre

1

Le problème est que dans chaque demande dans votre couche bussiness vous avez réellement créer un nouveau contexte d'EF. Cela signifie que lorsque vous récupérez des données par la méthode ShowCategory, EF ne suit pas les modifications de l'objet Category retourné lorsque vous l'avez placé dans la méthode AddProduct.

Généralement, le contexte EF est partagé pour l'ensemble de la requête au serveur. Si vous utilisez juste une catégorie de contexte ne sera pas dupliquée.

vous devriez juste mettre champ privé dans votre couche bussiness classe

private FlipkartContext _flipkartDBContext; 

et initialiser dans le constructeur de cette classe

_flipkartDBContext = new FlipkartContext(); 

et vous pouvez simplement utiliser qu'une instance de celui-ci en tout

+0

Merci @jgasiorowski. C'était le problème exact. Je crois que l'approche que vous avez mentionnée devrait être la pratique idéale. Dommage que les formations ne couvrent pas cela :(Merci encore pour votre aide rapide! – ishanmeh

+0

@ ishanmeh Ce n'est pas la façon exacte dont il est abordé dans les solutions.Peuple les gens utilisent Dependecy Injection pour cela.Vérifiez que vous devriez jeter un oeil sur ce sujet, il est couramment utilisé et je crois qu'il sera également utile dans vos futurs projets;) – jgasiorowski