2012-04-06 70 views
3

我想使用dropdownList與modelId和categoryId兩個外鍵。 我正在使用ViewBag和selectList。ViewBag多個SelectList下拉列表

public ActionResult Create() 
    { 
     ViewBag.categoryId = new SelectList(db.Category, "categoryId", "name"); 
     ViewBag.modelId = new SelectList(db.Model, "modelId", "name"); 
     return View(); 
    } 

    // 
    // POST: /Product/Create 

    [HttpPost] 
    public ActionResult Create(Product product) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Product.Add(product); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     ViewBag.categoryId = new SelectList(db.Category, "categoryId", "name", product.categoryId); 
     ViewBag.modelId = new SelectList(db.Model, "modelId", "name", product.modelId); 
     return View(product); 
    } 

這裏是我的Create.cshtml。

<div class="editor-label"> 
     @Html.LabelFor(model => model.Category) 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownList("categoryId", "--Select--") 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.Model) 
    </div> 

    <div class="editor-field"> 
     @Html.DropDownList("modelId", "--Select--") 
    </div> 

當我按下提交按鈕,錯誤上來, 「具有相同鍵的項已被添加」 是什麼問題呢?在模型中有問題嗎?

這是我的模特。

--Prodruct.cs-- 

public class Product 
{ 
    [Key] public int productId { get; set; } 

    [Required(ErrorMessage = "Please select category")] 
    public int categoryId { get; set; } 

    [Required(ErrorMessage = "Please select model")] 
    public int modelId { get; set; } 

    [DisplayName("Model name")] 
    public String model { get; set; } 

    public virtual Category Category { get; set; } 
    public virtual Model Model { get; set; } 
} 

--Category.cs-- 
public class Category 
{ 
    [Key] public int categoryId { get; set; } 
    public String name { get; set; } 
} 

--Model.cs-- 
public class Model 
{ 
    [Key] public int modelId { get; set; } 
    public String name { get; set; } 
} 

--RentalDB.cs-- 
public class rentalDB : DbContext 
{ 
    public DbSet<Product> Product { get; set; } 
    public DbSet<Model> Model { get; set; } 
    public DbSet<Customer> Customer { get; set; } 
    public DbSet<Order> Order { get; set; } 
    public DbSet<Cart> Cart { get; set; } 
    public DbSet<Category> Category { get; set; } 
    public DbSet<OrderDetails> OrderDetails { get; set; } 

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

哪裏出錯了?創建中的索引頁面可以獲取類別數據和模型數據。但是,當我提交時,它有錯誤,'已添加具有相同密鑰的項目'。 你能幫我解決問題嗎? 謝謝。

- 添加更多編碼 -

我正在使用此LINQ。可能這裏有問題。

如何在此處添加「模型」實體?

var product = from a in db.Product.Include(a => a.Category) 
         select a; 
+0

我加了一個關於如何完成的詳細答案。 – 2012-04-06 13:24:55

回答

2

這是我怎麼會做呢..

我建議你不要把你的域模型的觀點,而是爲每個視圖創建一個視圖模型。這樣做,你將只包括屏幕上需要的東西。

爲您創建視圖中創建一個新的視圖模式:

public class ProductCreateViewModel 
{ 
    // Include other properties if needed, these are just for demo purposes 

    public string Name { get; set; } 
    public string SKU { get; set; } 
    public string LongDescription { get; set; } 

    // This is the unique identifier of your category, 
    // i.e. foreign key in your product table 
    public int CategoryId { get; set; } 
    // This is a list of all your categories populated from your category table 
    public IEnumerable<Category> Categories { get; set; } 

    // This is the unique identifier of your model, 
    // i.e. foreign key in your product table 
    public int ModelId { get; set; } 
    // This is a list of all your models populated from your model table 
    public IEnumerable<Model> Models { get; set; } 
} 

分類等級:

public class Category 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

模型類:

public class Model 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

在您創建視圖,您將有以下:

@model MyProject.ViewModels.ProductCreateViewModel 

@using (Html.BeginForm()) 
{ 
    <table> 
      <tr> 
       <td><b>Category:</b></td> 
       <td> 
        @Html.DropDownListFor(x => x.CategoryId, 
         new SelectList(Model.Categories, "Id", "Name", Model.CategoryId), 
         "-- Select --" 
        ) 
        @Html.ValidationMessageFor(x => x.CategoryId) 
       </td> 
      </tr> 
      <tr> 
       <td><b>Model:</b></td> 
       <td> 
        @Html.DropDownListFor(x => x.ModelId, 
         new SelectList(Model.Models, "Id", "Name", Model.ModelId), 
         "-- Select --" 
        ) 
        @Html.ValidationMessageFor(x => x.ModelId) 
       </td> 
      </tr> 
    </table> 

    <!-- Add other HTML controls if required and your submit button --> 
} 

你創建的操作方法:

public ActionResult Create() 
{ 
    ProductCreateViewModel viewModel = new ProductCreateViewModel 
    { 
      // Here you do database calls to populate your dropdowns 
      Categories = categoryService.GetAllCategories(), 
      Models = modelService.GetAllModels() 
    }; 

    return View(viewModel); 
} 

[HttpPost] 
public ActionResult Create(ProductCreateViewModel viewModel) 
{ 
    // Check that viewModel is not null 

    if (!ModelState.IsValid) 
    { 
      viewModel.Categories = categoryService.GetAllCategories(); 
      viewModel.Models = modelService.GetAllModels(); 

      return View(viewModel); 
    } 

    // Mapping 
    Product product = ... // Do your mapping here 

    // Insert product in database 
    productService.Insert(product); 

    // Return the view where you need to be 
} 

我也建議你使用AutoMapper做映射你的域模型和視圖模型之間。我也建議你看看Fluent Validation來照顧你的視圖模型驗證。

我希望這會有所幫助。

修訂ANSWER

這是用來讓所有的類別可能看起來像這樣的服務:

public class CategoryService : ICategoryService 
{ 
    private readonly ICategoryRepository categoryRepository; 

    public CategoryService(ICategoryRepository categoryRepository) 
    { 
      // Check if category repository is not null, throw exception if it is 

      this.categoryRepository = categoryRepository; 
    } 

    public IEnumerable<Category> GetAllCategories() 
    { 
      return categoryRepository.GetAllCategories(); 
    } 
} 

categoryRepository由Autofac注入。

分類服務接口:

public interface ICategoryService 
{ 
    IEnumerable<Category> GetAllCategories(); 
} 

我目前還在第一次使用Entity Framework 4.1代碼。

我的類別庫:

public class CategoryRepository : ICategoryRepository 
{ 
    MyContext db = new MyContext(); 

    public IEnumerable<Category> GetAllCategories() 
    { 
      return db.Categories 
       .OrderBy(x => x.Name); 
    } 
} 

我的類別庫接口:

public interface ICategoryRepository 
{ 
    IEnumerable<Category> GetAllCategories() 
} 
+0

謝謝你的回覆。你知道任何ViewModel的例子嗎?我想我需要了解ViewModel的更多細節。如果你知道一些網站,請告訴我。我無法正確理解ViewModel。如果您已經瞭解了ViewModel教程,請告訴我。謝謝! – wholee1 2012-04-06 14:43:02

+0

我的榮幸。只是谷歌它。基本上,視圖模型僅包含要在視圖中使用的字段,例如,如果您想添加新用戶,那麼您的字段只有名字,姓氏和年齡,而不是在用戶對象中使用所有內容。 – 2012-04-06 14:50:25

+0

我想通過使用ViewModel添加它的字段與原始實體中的字段名稱相同嗎?我想了解ViewModel是如何工作的。在你的編碼中,'viewModel.Categories = categoryService.GetAllCategories();'我如何聲明categoryService? – wholee1 2012-04-06 14:57:32

0
public class Test 
{ 
    rentalDB db = new rentalDB(); 
    public Product LoadProductById(int pId) 
    { 
     return db.Products.Include(p => p.Model).Include(p => p.Category).Where(p => p.productId == pId).SingleOrDefault(); 
    } // To get specific product. 

    public IEnumerable<Product> LoadAllProducts() 
    { 
     return db.Products.Include(p => p.Model).Include(p => p.Category).ToList(); 
    } // To get all products. 
} 

我已經改變了你的DbSet到產品使其更加清晰。這是您如何加載一個產品或所有產品的所有參考,以便迭代它們。