【问题标题】:Copy oracle specific columns of a table in .net collection like a List复制.net集合中表的oracle特定列,如列表
【发布时间】:2014-10-31 15:30:34
【问题描述】:

我正在开发一个 asp.net 应用程序。用户可以上传一个 csv 文件,其中每行由 3 个字段名称、姓氏、年龄组成。我还有一个 oracle 数据库,其中有一个由姓名、姓氏、年龄、国家组成的表。在 csv 的每一行,我必须检查我的表中是否已在我的表中注册了姓名。因此,就性能而言,它的成本非常高。由于我的表只每晚更新一次,所以我想在 .net 集合中复制我的 oracle 表的名字和姓氏,就像一个列表一样。所以我将在每个 csv 行检查字段是否在我的列表中,而不必执行 sql 请求,我将在其中进行选择计数。所以我有两个问题: 这种在 .net 集合中复制我的表的解决方案看起来不错吗? 如果是的话,你能解释一下如何在.net 集合中复制oracle 表的内容吗?

提前致谢

【问题讨论】:

    标签: c# asp.net oracle csv


    【解决方案1】:

    事实是,您最好的选择是将所有这些都交给 Oracle。所以..

    第一

    1. 在您的数据库中创建一个临时表,其结构为(姓名、姓氏、年龄)。

    然后

    1. 将您的 CSV 加载到临时表中。
    2. 从您的临时表中选择数据antijoined针对您的目标表。
    3. 将其余部分(即目标数据库表中不存在的 CSV 行)加载到目标数据库表中。

    到此,一切就绪。老实说,您不可能在 .NET 端比在 Oracle 端更快地做到这一点。

    步骤 2+3 将是:

    insert into target_table (name, surname, age)
    select X.name, X.surname, X.age
    from temporary_table X
    where not exists (
            select 1
            from target_table Y
            where Y.name = X.name
                and Y.surname = X.surname
        );
    

    至于第 1 步:使用 C# 中的数组绑定将数据批量发送到 Oracle,或者干脆忘记 C# 并使用 Oracle SQL*Loader 或外部表以最快的方式。

    【讨论】:

      【解决方案2】:

      我认为最有效的方法是创建一个通用模型类来存储每个用户。像这样……

      public class User
      {
          public string Name { get; set; }
          public string Surname { get; set; }
          public int Age { get; set; }
          public string Country { get; set; }
      
          // This comparer will be used to find records that exist or don't exist.
          public class KeyFieldComparer : IEqualityComparer<User>
          {
              public bool Equals(User u1, User u2)
              {
                  return u1.Name == u2.Name && u1.Surname == u2.Surname;
              }
      
              public int GetHashCode(User u)
              {
                  return u.Name.GetHashCode() ^ u.Surname.GetHashCode();
              }
          }
      }
      

      现在将 CSV 文件和 Oracle 表都加载到 List&lt;User&gt; 对象中...

      List<User> csvList;
      List<User> oracleList;
      

      当两个列表都填充了数据时,很容易查看每个列表中已经存在的内容,而不是访问数据库...

      // This will filter users that are in the CSV file that don't already exist in oracle.
      var newUsers = csvList.Except(oracleList, new User.KeyFieldComparer());
      

      然后您可以遍历每个新用户并插入它们...

      foreach (var newUser in newUsers)
          InsertNewUser(newUser);
      

      希望这有帮助。


      更新:
      我最喜欢的将数据从数据库加载到列表的方法是使用微 ORM,例如 Insight.Database。只需在 nuget 中搜索 Insight.Database 并安装显示 Insight.Database.Providers.Oracle 的那个。然后您可以像这样将表查询到内存中...

      List<User> oracleList;
      using (var db = new OracleConnection(ConnectionString))
      {
          oracleList = db.QuerySql<User>("SELECT Name, Surname, Age, Country FROM Users");
      }
      

      只要您的类模型中的属性与您选择的列的名称匹配,它就会正确映射它们(不区分大小写)。

      【讨论】:

      • 好的,谢谢,我对其中的一部分提出了一些问题,但仍不清楚。如何继续在我的数据库中使用我的用户表的列名和姓氏填充 oraclelist,在性能方面效率最高且成本更低。
      • 当我尝试使用查询方法时出现此错误:“Oracle.DataAccess.Client.OracleConnection”不包含“查询”的定义,并且没有扩展方法“查询”接受第一个可以找到“Oracle.DataAccess.Client.OracleConnection”类型的参数(您是否缺少 using 指令或程序集引用?)
      • 在解决方案资源管理器中右键单击项目。单击管理 nuget 包。确保在左侧选择 Online -> nuget.org。在搜索中键入“insight.database”。在搜索结果中选择 Insight.Database.Providers.Oracle 并单击安装。这应该添加必要的扩展方法。参考:github.com/jonwagner/Insight.Database/wiki/A-Quick-Tour
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 2015-09-24
      • 2019-04-30
      • 2019-02-18
      • 1970-01-01
      相关资源
      最近更新 更多