1. cshtml頁面 form
<form id="form" method="post" action="/SaveValueBatch" enctype="multipart/form-data"> <input type="file" name="uploadExcel" style="width:200px;" /> </form>
2. controller
[HttpPost] public ActionResult SaveValueBatch(IFormCollection form) { try { var files =Request.Form.Files.Where(x => x.Name.Equals("uploadExcel")); //非空限制 if (files == null || files.Count() <= 0) { return Json(new { isSuccess = false, message = "請選擇要上傳的Excel文件" }, "text/html"); } //格式限制 var allowType = new string[] { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}; if (files.Any(b => !allowType.Contains(b.ContentType))) { return Json(new { isSuccess = false, message = "只能上傳Excel 2007 格式文件" }, "text/html"); } //大小限制 if (files.Sum(b => b.Length) >= 1024 * 1024 * 4) { return Json(new { isSuccess = false, message = "上傳文件的總大小只能在4M以下" }, "text/html"); } //寫入服務器磁盤 foreach (var file in files) { var fileName = file.FileName; var path = Path.Combine(_host.ContentRootPath+ "/Upload", fileName); using (var stream = System.IO.File.Create(path)) { file.CopyTo(stream); } } return Json(new { isSuccess = true, message = "保存成功" }, "text/html"); } catch (Exception e) { return Json(new { isSuccess = false, message = "保存失敗:" + e.InnerException.Message }, "text/html"); } }
private IHostingEnvironment _host; public ExcelController(IHostingEnvironment host) { _host = host; }
3. 讀取excel內容,用context.AddRange 插入數據(這個是用Merge SQL語句操作的.), 之前用SQLServer 2005,不支持Merge語句, 只有升級到到新版本. 我選擇升級到SQL2014了. (SQL 2016/2017開始支持Linux,暫時我不需要)
using (ExcelPackage ep = new ExcelPackage(new FileInfo(path))) { ExcelWorksheet ws = ep.Workbook.Worksheets[0]; //第1張Sheet int colStart = ws.Dimension.Start.Column; //工作區開始列,start=1 int colEnd = ws.Dimension.End.Column; //工作區結束列 int rowStart = ws.Dimension.Start.Row; //工作區開始行號,start=1 int rowEnd = ws.Dimension.End.Row; //工作區結束行號 Guid[] columnsGuid = new Guid[colEnd+1]; //skip zero index for (int k = colStart; k <= colEnd; k++) { string columnName = ws.Cells[1, k].Text;//列名 } for (int i = rowStart + 1; i <= rowEnd; i++) //第1行是列名,跳過 { Guid rowGuid = Guid.NewGuid(); for (int j = colStart; j <= colEnd; j++) { var info = new BaseInfo(); info.Id = 0; info.RowGuid = rowGuid; info.Guid = columnsGuid[j]; info.FieldValue = ws.Cells[i, j].Text; infos.Add(info); } } _context.ChangeTracker.AutoDetectChangesEnabled = false; _context.AddRange(infos); _context.SaveChanges(); _context.ChangeTracker.AutoDetectChangesEnabled = true; }
有一個注意點: 如果你是用excel上傳數據,同時做新增和修改的話, DB已有的數據,不要放在Infos 這個數組 _context.AddRange(infos);
因為如果你把DB已有的數據再AddRange,它會嘗試插入一條新的記錄,SQL語句里包括主鍵,而你的主鍵是自動生成的話.就會出現這個錯誤
System.Data.SqlClient.SqlException (0x80131904): 當 IDENTITY_INSERT 設置為 OFF 時,不能為表 'XXXXXX' 中的標識列插入顯式值。