c# webapi实现前端的上传一个excle表格,获取表格的表头,将表头内容创建实体类,并将实体类创建数据库表,用户每次上传表,就删除数据库中的原始表,在进行上述流程,然后能对数据库数据进行分页查询
1.创建数据库上下文
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
}
2.模型类
public class UploadModel
{
public IFormFile File { get; set; }
public string TableName { get; set; }
}
public class QueryModel
{
public string TableName { get; set; }
public int Page { get; set; } = 1;
public int PageSize { get; set; } = 10;
}
public class PagedResult
{
public List<Dictionary<string, object>> Data { get; set; }
public int Total { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
}
3.简化的excel上传控制器
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using OfficeOpenXml;
using System.Data;
[ApiController]
[Route("api/excel")]
public class ExcelController : ControllerBase
{
private readonly IConfiguration _configuration;
public ExcelController(IConfiguration configuration)
{
_configuration = configuration;
}
// 1. 上传Excel并创建表
[HttpPost("upload")]
public async Task<IActionResult> UploadExcel([FromForm] UploadModel model)
{
if (model.File == null || model.File.Length == 0)
return BadRequest("请选择文件");
if (string.IsNullOrEmpty(model.TableName))
return BadRequest("请输入表名");
using var stream = model.File.OpenReadStream();
using var package = new ExcelPackage(stream);
var worksheet = package.Workbook.Worksheets[0];
// 获取表头
var headers = new List<string>();
for (int col = 1; col <= worksheet.Dimension.Columns; col++)
{
var header = worksheet.Cells[1, col].Text?.Trim();
if (!string.IsNullOrEmpty(header))
headers.Add(header);
}
if (headers.Count == 0)
return BadRequest("Excel中没有表头");
// 分析数据类型(简单版本,只检查第一行数据)
var columnTypes = new List<string>();
for (int col = 1; col <= headers.Count; col++)
{
var cellValue = worksheet.Cells[2, col].Text;
columnTypes.Add(GetColumnType(cellValue));
}
// 创建数据库表
var connectionString = _configuration.GetConnectionString("DefaultConnection");
using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
// 删除已存在的表
var dropSql = $"IF OBJECT_ID('{model.TableName}', 'U') IS NOT NULL DROP TABLE [{model.TableName}]";
using var dropCmd = new SqlCommand(dropSql, connection);
await dropCmd.ExecuteNonQueryAsync();
// 创建新表
var columns = new List<string>();
columns.Add("[Id] INT IDENTITY(1,1) PRIMARY KEY");
for (int i = 0; i < headers.Count; i++)
{
columns.Add($"[{headers[i]}] {columnTypes[i]}");
}
var createSql = $"CREATE TABLE [{model.TableName}] ({string.Join(", ", columns)})";
using var createCmd = new SqlCommand(createSql, connection);
await createCmd.ExecuteNonQueryAsync();
// 插入数据
for (int row = 2; row <= worksheet.Dimension.Rows; row++)
{
var values = new List<string>();
for (int col = 1; col <= headers.Count; col++)
{
var cellValue = worksheet.Cells[row, col].Text;
var sqlValue = FormatSqlValue(cellValue, columnTypes[col - 1]);
values.Add(sqlValue);
}
var insertSql = $"INSERT INTO [{model.TableName}] ({string.Join(", ", headers)}) VALUES ({string.Join(", ", values)})";
using var insertCmd = new SqlCommand(insertSql, connection);
await insertCmd.ExecuteNonQueryAsync();
}
return Ok(new {
Success = true,
TableName = model.TableName,
Rows = worksheet.Dimension.Rows - 1
});
}
// 2. 分页查询数据
[HttpPost("query")]
public async Task<IActionResult> QueryData([FromBody] QueryModel model)
{
var connectionString = _configuration.GetConnectionString("DefaultConnection");
using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
// 获取总行数
var countSql = $"SELECT COUNT(*) FROM [{model.TableName}]";
using var countCmd = new SqlCommand(countSql, connection);
var total = Convert.ToInt32(await countCmd.ExecuteScalarAsync());
// 分页查询数据
var offset = (model.Page - 1) * model.PageSize;
var querySql = $@"
SELECT * FROM [{model.TableName}]
ORDER BY Id
OFFSET {offset} ROWS
FETCH NEXT {model.PageSize} ROWS ONLY";
using var queryCmd = new SqlCommand(querySql, connection);
using var reader = await queryCmd.ExecuteReaderAsync();
var result = new List<Dictionary<string, object>>();
while (await reader.ReadAsync())
{
var row = new Dictionary<string, object>();
for (int i = 0; i < reader.FieldCount; i++)
{
row[reader.GetName(i)] = reader.IsDBNull(i) ? null : reader.GetValue(i);
}
result.Add(row);
}
return Ok(new PagedResult
{
Data = result,
Total = total,
Page = model.Page,
PageSize = model.PageSize
});
}
// 3. 获取所有表名
[HttpGet("tables")]
public async Task<IActionResult> GetTables()
{
var connectionString = _configuration.GetConnectionString("DefaultConnection");
using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
var sql = @"
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME NOT LIKE 'sys%'
ORDER BY TABLE_NAME";
using var cmd = new SqlCommand(sql, connection);
using var reader = await cmd.ExecuteReaderAsync();
var tables = new List<string>();
while (await reader.ReadAsync())
{
tables.Add(reader.GetString(0));
}
return Ok(tables);
}
// 4. 删除表
[HttpDelete("table/{tableName}")]
public async Task<IActionResult> DeleteTable(string tableName)
{
var connectionString = _configuration.GetConnectionString("DefaultConnection");
using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
var sql = $"IF OBJECT_ID('{tableName}', 'U') IS NOT NULL DROP TABLE [{tableName}]";
using var cmd = new SqlCommand(sql, connection);
await cmd.ExecuteNonQueryAsync();
return Ok(new { Success = true, Message = $"表 {tableName} 已删除" });
}
// 辅助方法:确定列类型
private string GetColumnType(string value)
{
if (string.IsNullOrEmpty(value))
return "NVARCHAR(255)";
if (int.TryParse(value, out _))
return "INT";
if (decimal.TryParse(value, out _))
return "DECIMAL(18,2)";
if (DateTime.TryParse(value, out _))
return "DATETIME";
return "NVARCHAR(255)";
}
// 辅助方法:格式化SQL值
private string FormatSqlValue(string value, string columnType)
{
if (string.IsNullOrEmpty(value))
return "NULL";
if (columnType.StartsWith("NVARCHAR") || columnType.StartsWith("DATETIME"))
return $"'{value.Replace("'", "''")}'";
return value;
}
}