Read Excel Data and Convert to DataTable without using OLE DB in C#

Introduction
 
There are many ways available to convert excel file to DataTable, I found this is the best approach to do so. 
 
In your controller, you can add an action method UploadRewardsMembership(), which will read the excel file and convert the content into a data table. Then form the UploadRewardsMembership method, you can call the repository method InsertFCReward() to insert the data to the database.
  1. public ActionResult UploadRewardsMembership()  
  2. {  
  3.    try  
  4.    {  
  5.       HttpPostedFileBase fileBase;  
  6.       DataTable dataTable = new DataTable();  
  7.       if(Request.Files.Count > 0)  
  8.       {  
  9.          foreach (string file in Request.Files)  
  10.             {  
  11.                fileBase = Request.Files[file] as HttpPostedFileBase;  
  12.                if (fileBase != null && fileBase.ContentLength > 0)  
  13.                {  
  14.                   Stream stream = fileBase.InputStream;  
  15.                   IExcelDataReader reader = null;  
  16.                   if (fileBase.FileName.EndsWith(".xls"))  
  17.                   {  
  18.                      reader = ExcelReaderFactory.CreateBinaryReader(stream);  
  19.                   }  
  20.                   else if (fileBase.FileName.EndsWith(".xlsx"))  
  21.                   {  
  22.                      reader = ExcelReaderFactory.CreateOpenXmlReader(stream);  
  23.                   }  
  24.                   var result = reader.AsDataSet(new ExcelDataSetConfiguration()  
  25.                   {  
  26.                      ConfigureDataTable = (_) => new ExcelDataTableConfiguration()  
  27.                      {  
  28.                         UseHeaderRow = true  
  29.                      }  
  30.                   });  
  31.                   dataTable = result.Tables[0];  
  32.                   int resultCount = InsertFCReward(dataTable);  
  33.                   if (resultCount == -1)  
  34.                   {  
  35.                      ViewBag.FCRewardMessage = fileBase.FileName + " is not in correct format.";  
  36.                      break;  
  37.                   }  
  38.                   reader.Close();  
  39.             }  
  40.          }  
  41.       }  
  42.       else  
  43.       {  
  44.          ViewBag.FCRewardMessage = "Please select a file for upload.";  
  45.       }  
  46.       var admin = new Admin  
  47.       {  
  48.          Page = new AdminPage()  
  49.          {  
  50.             CurrentPage = 1,  
  51.             PageSize = 50,  
  52.          },  
  53.       };  
  54.       admin.RewardMemberships = GetRewardsMembershipDetails(admin.Page);  
  55.       return PartialView("_MembershipGrid", admin);  
  56.    }  
  57.    catch(Exception ex)  
  58.    {  
  59.       log.Error("UploadRewardsMembership" + string.Concat(DateTime.Now.ToString(CultureInfo.InvariantCulture), " ", ex.Message), ex);  
  60.       return base.DisplaySessionError();  
  61.    }  
  62. }  
In repository, you can define InsertFCReward(), which will accept a data table. By using entity frame work, you can push the data to the data base. This method will return, the number of records inserted into the DB.
  1. public int InsertFCReward(DataTable importdt)  
  2. {  
  3. int insertCount = 0;  
  4. DataColumnCollection columns = importdt.Columns;  
  5. if (!(columns.Count == 9 && columns.Contains("FirstName") && columns.Contains("LastName") && columns.Contains("Email") && columns.Contains("IceMemberId")  
  6. && columns.Contains("expiration") && columns.Contains("created") && columns.Contains("Phone") && columns.Contains("Lead Source")  
  7. && columns.Contains("Member Class")))  
  8. {  
  9. return -1;  
  10. }  
  11.   
  12. using (var context = new FCRewardsMebershipEntities())  
  13. {  
  14. for (int i = 0; i < importdt.Rows.Count; i++)  
  15. {  
  16.    FCReward fCReward = new FCReward();  
  17.    fCReward.FirstName = importdt.Rows[i]["FirstName"].ToString();  
  18.    fCReward.LastName = importdt.Rows[i]["LastName"].ToString();  
  19.    fCReward.Email = importdt.Rows[i]["Email"].ToString();  
  20.    fCReward.MemberID = importdt.Rows[i]["IceMemberId"].ToString();  
  21.    fCReward.Expiration = Convert.ToDateTime(importdt.Rows[i]["expiration"]);  
  22.    fCReward.CreatedDate = DateTime.Now;  
  23.    fCReward.CreatedBy = "RedDox";  
  24.    fCReward.Phone = importdt.Rows[i]["Phone"].ToString();  
  25.    fCReward.LeadSource = importdt.Rows[i]["Lead Source"].ToString();  
  26.    fCReward.MemberClass = importdt.Rows[i]["Member Class"].ToString();  
  27.   
  28.    context.FCRewards.Add(fCReward);  
  29. }  
  30. insertCount = context.SaveChanges();  
  31. }  
  32. return insertCount;  
  33. }  
Add a script tag, where the js method uploadFCReward() will be defined. It will call the UploadRewardsMembership() method of Admin controller and will bind a partial view with the data inserted to the data base.
  1. <script type="text/javascript">  
  2. function uploadFCReward(e) {   
  3. var fileUpload = $("#postedFile").get(0);  
  4. var files = fileUpload.files;  
  5. var fileData = new FormData();  
  6. for (var i = 0; i < files.length; i++) {  
  7. fileData.append(files[i].name, files[i]);  
  8. }  
  9. $.ajax({  
  10. url: '@Url.Action("UploadRewardsMembership", "Admin")',  
  11. type: "POST",  
  12. contentType: false,  
  13. processData: false,  
  14. data: fileData,  
  15. success: function (data) {  
  16. $('#postedFile').val('');  
  17. $('#MembershipGrid').html(data);  
  18. console.log("success");  
  19. },  
  20. error: function (e) {  
  21. console.log(e);  
  22. $('#MembershipGrid').html('');  
  23. },  
  24. });  
  25. }  
  26. </script>  

In view, one file upload field with a upload button will be there. On click of Upload button, uploadFCReward() method will be invoked.

  1. @using (Html.BeginForm("GetRewardsMembership""Admin", FormMethod.Post, new { enctype = "multipart/form-data", id = "GetRewardsMembershipForm" }))  
  2. {  
  3.    @Html.AntiForgeryToken()  
  4.    @Html.ValidationSummary()  
  5.    <div class="form-horizontal">  
  6.    <hr />  
  7.    @Html.ValidationSummary(true""new { @class = "text-danger" })  
  8.    <div class="form-group">  
  9.    @Html.LabelFor(model => model.FileModel.files, htmlAttributes: new { @class = "control-label col-md-2" })  
  10.    <div class="col-lg-3 col-md-3 col-xs-3">  
  11.    @Html.TextBoxFor(model => model.FileModel.files, ""new { @class = "form-control", @type = "file", @multiple = "multiple", id = "postedFile"    })  
  12.    @Html.ValidationMessageFor(model => model.FileModel.files, ""new { @class = "text-danger" })  
  13.    </div>  
  14.    <div class="col-lg-3 col-md-3 col-xs-3">  
  15.    <input type="button" onclick="return uploadFCReward(event);" title="Upload" value="Upload" class="btn btn-default btn-sm" />  
  16.    </div>  
  17.    </div>  
  18.    </div>  
  19. }  
The reason why I chose this way is if you want to use OLEDB, then you have to install that in your machine. If you want to publish it then in the remote system, OLEDB has to be installed as well.