【问题标题】:How to avoid duplicates when inserting data using OleDB and Entity Framework?使用 OleDB 和实体框架插入数据时如何避免重复?
【发布时间】:2021-11-02 13:40:34
【问题描述】:

我需要将 Excel 报告数据导出到公司数据库,但我的代码只是读取和插入而不检查重复,我尝试了 AddOrUpdate() 但我无法使其工作。

关于如何通过数据读取器结果并过滤已经存在的 ID 以便它们不会再次插入的任何想法?

DataView ImportarDatosSites(string filename)
        {
            string conexion = string.Format("Provider = Microsoft.ACE.OLEDB.12.0; Data Source={0}; Extended Properties= 'Excel 8.0;HDR=YES'" ,filename );
            using (OleDbConnection connection = new OleDbConnection(conexion))
            {
                connection.Open();
                OleDbCommand command = new OleDbCommand("SELECT * FROM [BaseSitiosTelemetria$]", connection);
                OleDbDataAdapter adaptador = new OleDbDataAdapter { SelectCommand = command };
                DataSet ds = new DataSet();
                adaptador.Fill(ds);
                DataTable dt = ds.Tables[0];
          
                using (OleDbDataReader dr = command.ExecuteReader())
                {
                    while (dr.Read())
                    {
                        var SiteID     = dr[1];
                        var ID_AA_FB   = dr[2];
                        var Address    = dr[3];
                        var CreateDate = dr[5];
                        var Tipo       = dr[7];
                        var Measures   = dr[9];
                        var Latitud    = dr[10];
                        var Longitud   = dr[11];

                        SitesMtto s = new SitesMtto();

                        s.siteIDDatagate      = SiteID.ToString();
                        s.idFieldBeat         = ID_AA_FB.ToString();
                        s.addressDatagate     = Address.ToString();
                        s.createDateDatagate  = Convert.ToDateTime(CreateDate);
                        s.typeDevice          = Tipo.ToString();
                        s.MeasuresDevice      = Measures.ToString();
                        if (Latitud.ToString() != "" && Longitud.ToString() != "")
                        {
                            s.latitudeSite  = Convert.ToDouble(Latitud);
                            s.longitudeSite = Convert.ToDouble(Longitud);
                        }

                      db.SitesMtto.Attach(s);
                      db.SitesMtto.Add(s);
                      db.SaveChanges();    
                    }

                    connection.Close();
                    return ds.Tables[0].DefaultView;
                }
            }
        }

【问题讨论】:

标签: c# entity-framework


【解决方案1】:

一种方法是设置一个 try catch 块,然后使用 tsql 设置您的主键索引。当发生约束错误时,它将引发您可以捕获的数据库错误。

【讨论】:

    【解决方案2】:

    当涉及到从外部来源的导入过程时,我建议使用暂存表方法。将 Excel/文件中的原始数据转储到干净的临时表中。 (首先对暂存表执行TRUNCATE TABLE 脚本)从那里您可以对 real 数据表执行带有连接的查询,以检测和忽略/更新可能的重复项,为任何暂存表插入实际行没有对应值的行。

    根据行数,我建议批量读取和插入。您也不需要同时调用Attach()Add(),只需将项目添加到 DbSet 就足够了:

    第 1 步:使用 db.Database.ExecuteSqlCommand("TRUNCATE TABLE stagingSitesMtto"); 刷新临时表

    第 2 步:打开数据读取器并将行批量插入到 stagingSitesMtto 表中。这假定 Excel/文件源中不包含重复的行。

    第 3 步:查询您的 stagingSitesMtto 在 PK/唯一键上加入您的 SitesMtto 表。这可能有点复杂,因为Join 通常用于执行 INNER JOIN,但我们需要 OUTER JOIN,因为我们将对没有相应站点的 StagingSites 感兴趣。

    var query = db.StagingSitesMtto
        .GroupJoin(db.SitesMto,
           staging => staging.SiteID,
           site => site.siteIDDatagate,
           (staging, site) => new 
           {
               Staging = staging,
               Site = site
           })
        .SelectMany(group => group.Site.DefaultIfEmpty(),
            (group, site) => new 
            {
                Staging = group.Staging,
                IsNew = site == null
            })
        .Where(x => x.IsNew)
        .Select(x => x.Staging)
        .ToList(); // Or run in a loop with Skip and Take
    

    这将选择所有没有对应实际行的暂存行。从那里您可以创建新的 SitesMtto 实体并从暂存行复制数据,将其添加到 db.Sites 并保存。如果要更新行以及插入,则可以返回 Staging 和 Site 以及 IsNew 标志,并使用 .Staging 中的值更新 .Site。启用更改跟踪后,如果值发生更改,现有站点将在 SaveShanges 上更新。

    免责声明:以上代码未经测试,只是根据内存和外部连接方法的参考编写的。见:How to make LEFT JOIN in Lambda LINQ expressions

    希望这能让您在处理导入时有所考虑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多