使用C#,EF和SQL Server,仅将不存在的行从Excel文件插入数据库

时间:2018-11-13 21:49:17

标签: c# sql-server excel entity-framework exceldatareader

我读取了一个Excel文件并将该数据插入数据库表中,但是每次执行此操作时,它都会添加现有行以及新数据,我只想插入表中尚未存在的行,我唯一的ID是当前时间戳。

例如,这是我第一次插入时当前发生的情况:

ExcelFile                           Database Table

a | b | date                        a | b | date
-----------                        ---------------
1 | 1 | 2018/02/12                  1 | 1 | 2018/02/12  
2 | 2 | 2018 /03/12                 2 | 2 | 2018 /03/12 

这是在我第二次插入时发生的:

ExcelFile                           Database Table

a | b | date                        a | b | date
-----------                        ---------------
1 | 1 | 2018/02/12                  1 | 1 | 2018/02/12  
2 | 2 | 2018 /03/12                 2 | 2 | 2018 /03/12 
3 | 3 | 2018 /04/12                 1 | 1 | 2018/02/12
                                    2 | 2 | 2018 /03/12 
                                    3 | 3 | 2018 /04/12

我使用Entity Framework来执行此操作,并使用ExcelDataReader包:

var result = reader.AsDataSet();

DataTable dt = new DataTable();
dt = result.Tables[0];      // here I store the data from the Excel file

foreach (DataRow row in dt.Rows)
{
    using (AppContext context = new AppContext())
    {
        Data data = new Data();
        string date = row.ItemArray[4].ToString();
        DateTime parseDate = DateTime.Parse(date);
        Data datos = new Data
                            {
                                a = row.ItemArray[0].ToString(),
                                b = row.ItemArray[1].ToString(),
                                c = row.ItemArray[2].ToString(),
                                d = row.ItemArray[3].ToString(),
                                e = parseDate
                            };
        context.Data.Add(datos);
        context.SaveChanges();
    }
}

是否可以过滤excel文件或进行比较?

我全是耳朵。

3 个答案:

答案 0 :(得分:0)

在添加之前检查现有行。以下应插入您计算parseDate的位置。

var existingRow = context.Data.FirstOrDefault(d=>d.e == parseDate); //Note that the ".e" should refer to your "date" field
if (existingRow != null)
{
  //This row already exists
}
else
{
  //It doesn't exist, go ahead and add it
}

答案 1 :(得分:0)

如果“ a”是表上的PK,并且在行之间是唯一的,那么在插入之前,我将通过ID检查现有行的存在。与Mike的响应类似,尽管一个考虑因素是表是否具有许多列,我会避免返回该实体,而只是使用.Any()

进行存在检查
if (!context.Data.Any(x => x.a == row.a)
  // insert the row as a new entity

此处需要说明的是,如果excel文件中包含编辑内容,而现有行中的数据发生了更改,则这将无法容纳。

对于批量导入过程,我通常会先通过将excel数据首先登台到登台表中来进行处理。 (在每次导入之前清除登台表)从那里,我将有实体映射到登台表,而实体则映射到“真实”表。如果存在可以从文件中为每个记录提取的“修改日期”,那么我还将存储导入日期/时间作为应用程序的一部分,以便在选择要从登台表中导入的行时,仅获取记录修改日期/时间>上次导入日期/时间的位置。从那里,您可以批量查询暂存表中的数据,并查找新记录与现有修改。我发现迁移双方的查询实体都比处理导入中的内存块更灵活。对于小的导入来说,这可能不值得,但是对于较大的文件(您希望使用较小的子集和过滤),可以使事情变得更容易。

答案 2 :(得分:0)

在@MikeH的帮助下,我可以完全执行所需的操作 这样,仅添加了具有不同DateTime的行(在我的情况下,DateTime始终是升序值。)

foreach (DataRow row in dt.Rows) // dt = my dataTable loaded with ExcelDataReader
                    {
                        using (AppContext context = new AppContext())
                        {
                            string date = row.ItemArray[4].ToString(); 
                            DateTime parseDate = DateTime.Parse(date); // I did a parse because the column "e" only accepted DateTime and not String types.

                            var existingRow = context.Data.FirstOrDefault(d => d.e == parseDate);
                            if (existingRow != null)
                            {
                                Console.WriteLine("Do Nothing");
                            }
                            else
                            {
                                Data datos = new Data
                                {
                                    a = row.ItemArray[0].ToString(),
                                    b = row.ItemArray[1].ToString(),
                                    c = row.ItemArray[2].ToString(),
                                    d = row.ItemArray[3].ToString(),
                                    e = parseDate
                                };
                                context.Data.Add(datos);
                                context.SaveChanges();
                            }
                        }
                    }