2017-02-16 9 views
0

ユーザーがCategory objectsを追加できるCMSシステムを持っている場合、ユーザーは作成したカテゴリをクリックしてProduct objectsを追加できます。エンティティテーブルを持つデータベースにCSVデータを追加する:CategoryName列に基づく製品とカテゴリ

私は現在CSV data import formを開発しています。ユーザーは同じことをすることができますが、1つのCSVファイルをアップロードする必要があります。

CSVファイルのデータ(網掛けの灰色)は、製品のリストです。注 - 各製品のカテゴリ名の列を:

CSV_Data.png

これは、製品やカテゴリクラスである:私は現在、カテゴリと製品の間で持って

public class Product 
{ 
    public int Id { get; set; } 
    public string Barcode { get; set; } 
    [Required] 
    public string Name { get; set; } 
    public string Description { get; set; } 
    [Required] 
    public Byte[] Image { get; set; } 
    [Required] 
    public Decimal Price { get; set; } 
    [Required] 
    public bool ShowOnIndex { get; set; } 
} 

public class Category 
{ 
    public int Id { get; set; } 
    [Required] 
    public string Name { get; set; } 
    [Required] 
    public Byte[] Image { get; set; } 
    public virtual ICollection<Product> Products { get; set; } 
} 

関係はOne-to-Manyです。カテゴリには多くの製品があり、製品には1つのカテゴリしかありません。 CategoryIdは、SQL ServerのProductsテーブルの外部キーです。

私は自分のASP.NET MVCアプリケーションにユーザーがCSVファイルをアップロードし、アップロードしてAppDataフォルダに保存できるフォームを持っています。 CSVアップロードの投稿リクエストは、以下のコードに進みます。私は私のデータベースに正しく製品をインポートできるようにするには、CSVファイルからデータを分割する必要がある場所はここにある:

public static IEnumerable<Product> CSVToList(HttpPostedFileBase CSVFile) 
     { 

      if (CSVFile == null || CSVFile.ContentLength == 0) 
      { 
       throw new InvalidOperationException("No file has been selected for upload or the file is empty."); 
      } 

      // saves the file into a directory in the App_Data folder 
      var fileName = Path.GetFileName(CSVFile.FileName); 
      var path = Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data/"), fileName); 
      CSVFile.SaveAs(path); 

      CSVProducts = from line in File.ReadAllLines(path).Skip(1) 
          let columns = line.Split(',') 
          select new Product 
          { 
           Id = int.Parse(columns[0]), 
           Barcode = columns[13], 
           Name = columns[1], 
           CategoryName = columns[9], 
           Description = columns[2], 
           Price = int.Parse(columns[4]) 
          }; 


      return CSVProducts; 
     } 

しかし、上記のLINQクエリは、製品のリストを取得し、私のことができるようにする必要がありますカテゴリと製品の2つのエンティティに従って、これらをデータベースに格納します。誰かがこれを行う方法を提案することはできますか?私はLINQの新人です。

すべての一意のカテゴリ名をリストに抽出し、データベースのカテゴリテーブルに追加して、関連付けられたカテゴリ名に従って各製品を追加できるようにします。私はカテゴリが最初にインポートされると仮定します - 私はカテゴリのためのデータファイルを持っていません。通常、ユーザーは手動でカテゴリ名を書き込んでイメージを手動でアップロードし、現在のCMSにカテゴリを作成します。

+0

「string.split」よりも優れた仕事をする数多くのCSV解析ライブラリがあります。 CSVHelperたとえば – Plutonix

+0

または組み込みの['TextFieldParser'](https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser(v = vs.110).aspx)。 – dbc

答えて

0
// Creates Product objects from array of records 
// At present, images are assumed void 
// When CSV data contains images, then this code will need changing slightly. 

     var CSVProducts = from line in records 
          let columns = line.Split(',') 
          select new Product 
          { 
           Id = int.Parse(columns[0]), 
           Barcode = columns[13], 
           Name = columns[1], 
           CategoryName = CapitaliseWords(columns[9]), 
           Description = columns[2], 
           Price = decimal.Parse(columns[4]) 
          }; 

     ProductsList = CSVProducts.ToList(); 

     var CSVCategories = File.ReadLines(path).Skip(1) 
          .Select(l => l.Split(new[] { ',' })[9]) 
          .Where(category => category.Length > 0) 
          .Distinct(StringComparer.InvariantCultureIgnoreCase) 
          .Select(s => new Category { Name = CapitaliseWords(s) }); 

      CategoriesList = CSVCategories.ToList(); 
関連する問題