来自c#

时间:2017-02-22 20:42:49

标签: c# sql oracle vba

这是我在c#中的第一个项目。我在Access VBA方面有一点经验。我想将我的应用程序移动到独立程序。我正在查询具有培训类型和日期的表格。我想根据他们执行的日期比较一些类型的培训。三种培训类型是RWT010,RWP000和RWT010BP。如果RWT010BP存在并且更新,那么它是我唯一需要的。否则我需要RWT010和RWP000。我已经想出如何将值加载到变量中,但我需要能够使用它们。我想将dateTime值的名称作为同一行的trainType。这样我可以比较它们并输出正确的组合。

我的旧Access逻辑看起来像这样:

LABEL_DATE: IIf(IsNull([RWT010]),"RWT010BP: " & _
     Format([RWT010BP],"Short Date"),IIf([RWT010BP]>[RWT010],"RWT010BP: " & _
     Format([RWT010BP],"Short Date"),"RWT010: " & _
     Format([RWT010],"Short Date") & " & " & "RWP000: " & _
     Format([RWP000],"Short Date")))

这是我在c#中取得的成就:

Console.Write("Enter ID: ");
        int idnum = Convert.ToInt32(Console.ReadLine());
        string sql = "SELECT EXPID, TYPE, DATE_LATEST FROM TRAINING_TABLE where expid =" + idnum;



        OracleCommand cmd = new OracleCommand();

       cmd.Connection = conn;

        cmd.CommandText = sql;

        using (DbDataReader reader = cmd.ExecuteReader())
        {
            if (reader.HasRows)
            {

                while (reader.Read())
                {

                    int expid = reader.GetInt32(0);
                    string trainType = reader.GetString(1);
                    DateTime trainDate = reader.GetDateTime(2); 

1 个答案:

答案 0 :(得分:0)

原始的Access逻辑看起来像一个数据库行,其中包含三个日期字段[RWT010][RWT010BP][RWP000]。但是在Oracle中已经规范化,因此您需要返回多行,每行都有一个名为[DATE_LATEST]的日期时间字段,然后是名为[TYPE]的名称字段。等于"RWT010""RWT010BP""RWP000"

您正在考虑,您希望按名称处理这些RWP000日期值,就像在Access中一样。你是对的,这是最明智的做法,我会告诉你如何做。我误解了你的要求。

执行此操作的一种方法是编写复制Access逻辑的Oracle存储过程。这不是你提出的问题,但这是一种合法的方式。但是,由于数据库的变化,它会比Access版本更复杂,无论如何我多年没有编写Oracle SQL而且我没有Oracle服务器给我带来任意的,神秘的有关分号和空格的语法错误。

所以我要做的就是在C#中编写一个循环来从DB行中获取日期时间并将它们放在局部变量中,然后使用这些变量而不是字段在C#中复制Access逻辑。与Access版本相比,它有点冗长,但有时它会如何发展。

int idnum = Convert.ToInt32(Console.ReadLine());

string sql = "SELECT EXPID, TYPE, DATE_LATEST FROM TRAINING_TABLE where expid =" + idnum;

//  I don't know how you're using this so I'll just declare it here 
//  and leave that to you.
String dateLabel = "";

OracleCommand cmd = new OracleCommand();

cmd.Connection = conn;

cmd.CommandText = sql;

using (DbDataReader reader = cmd.ExecuteReader())
{
    DateTime? RWT010 = null;
    DateTime? RWT010BP = null;
    DateTime? RWP000 = null;

    //  No need to check reader.HasRows. If it has no rows, reader.Read()
    //  will return false the first time, that's all. 

    while (reader.Read())
    {
        //  Doesn't look to me like expid is used
        //int expid = reader.GetInt32(0);
        string trainType = reader.GetString(1);
        DateTime trainDate = reader.GetDateTime(2);

        switch (trainType) {
            case "RWT010":
                RWT010 = trainDate;
                break;
            case "RWT010BP":
                RWT010BP = trainDate;
                break;
            case "RWP000":
                RWP000 = trainDate;
                break;
        }
    }

    if (RWT010 == null || RWT010BP > RWT010) {
        dateLabel = String.Format("RWT010BP: {0:d}", RWT010BP);
    } else {
        dateLabel = String.Format("RWT010: {0:d} & RWP000: {1:d}", RWT010, RWP000); 
    }
}

最初的逻辑是:

  If RWT010 isn't null, 
      Do A
  Otherwise, if RWT010BP > RWT010
      ALSO do A
  But if none of the above, 
      Do B

前两个分支完全相同,所以我们可以将它们压缩成一个分支。

"不要重复自己",正如他们所说。你不想在一年之后回到这段代码,想知道这两行是否必须相同,然后猜错了,或者不注意它们是相同的,只改变一个或另一个。这只是一团糟。

如果你不是familiar with String.Format(),那就有很多了。在第一个参数字符串中,{0}表示"在此插入第二个参数&#34 ;; {1}表示"插入第三个",依此类推。 ":d"花括号里面是可选的;它意味着通过" d"作为其插入值的格式信息。 DateTime将解释" d"意思是"短日期"。你也可以这样做:

dateLabel = String.Format("RWT010BP: {0}", RWT010BP.Value.ToShortDateString());

或者像这样:

dateLabel = "RWT010BP: " + RWT010BP.Value.ToShortDateString();

我必须在该行中使用RWT010BP.Value而不仅仅是RWT010BP,因为RWT010BP在其之后声明为?。这使它成为一个可空的"值。常规DateTime不能为空,但我们需要在此处容纳空值。

如果你正在使用C#6,你可以这样做,我更喜欢。我上面没有使用它,因为我不知道你在哪个版本的C#上。总是喜欢最少量的"噪音"弄乱了代码。

dateLabel = $"RWT010BP: {RWT010BP:d}";

这是相同的":d"如上面的String.Format("{0:d}", ...)

还有一件事: idnum是一个int,但不能将字符串值连接成SQL字符串。这是一个巨大的安全漏洞,这里的人们(正确的,我害怕)会给你一个非常艰难的时间来考虑它。

使用OracleCommand.Parameters代替as shown in this answer。即使在这种情况下,我也会习惯使用它,就像条件反射一样。