【问题标题】:C# - SQL not finding duplicate value in the primary keyC# - SQL 在主键中找不到重复值
【发布时间】:2016-07-23 16:10:27
【问题描述】:

这有点难以解释,所以请多多包涵。
我通过控制台 c# 使用 sql 表。

我正处于最终用户需要能够做到的地步修改主键值,例如教室名称

当用户尝试编辑已经存在的主键值时,第一次循环 sql / c# catches 并给出 Exception 并且程序继续为正常将其循环回用户输入重复主键值的部分。

但是,当您再次尝试添加数据并碰巧添加一个已经作为主键值存在的值时,它不会t catch 第二轮。

这是一个时间表

  1. 进入新组菜单
  2. 更新组名称的详细信息,但该组名称已经 存在,因此它告诉最终用户再试一次并将它们循环回 要求添加新组的部分
  3. 最终用户添加正确的详细信息并继续使用 节目
  4. 稍后最终用户尝试更新组的详细信息并添加一个已经存在的名称,但是这一次它不会引发 Exception,而是在不应该的时候继续工作。



这是上面提到的循环背后的代码。

更新:添加所有模块以回答下面的一些 cmets。

static void editTable()
    {
        int j = 0;
    top:
        SQLCONN.Open();
        var TIME = DateTime.Now;
        SqlCommand cmd0 = new SqlCommand("SELECT * FROM dbo."+selectedDayTableToEdit+"Table", SQLCONN);
        SqlDataReader reader = cmd0.ExecuteReader();
        while (reader.Read())
        {
            int n = 1;
            int p = 1;
            Console.WriteLine("------------------------------------------------------------");
            Console.WriteLine("  [" + reader.GetValue(n).ToString() + " TIMES]     [TEACHER / CLASSROOM]      {0} " + TIME.ToString("HH:mm:ss"), selectedDayTitle);
            Console.WriteLine("------------------------------------------------------------");

            for (int i = 2; i < reader.FieldCount; i++)
            {
                Console.WriteLine(p +" - " + reader.GetName(i) + "      " + reader.GetValue(i));
                p++;
            }
        }

        SQLCONN.Close();
        repeat:
        Console.WriteLine();
        Console.WriteLine("Which group would you like to edit?");
        string Group = Console.ReadLine().ToUpper();
        Console.WriteLine("Enter {0}'s new group name if any", Group);
        string newGroup = Console.ReadLine().ToUpper();
        if (string.IsNullOrEmpty(newGroup))
        {
            check = true;
            newGroup = string.Format("{0}", Group);
        }
        else
        {
            check = false;
        }
        SQLCONN.Open();
        //update Group Name (SAT)
        try
        {
               if(check == false)
            {
        using (SqlCommand cmd = new SqlCommand("UPDATE " + selectedDayTableToEdit + "Table SET CLASSNAME=@CLASSNAME where CLASSNAME=@" + Group, SQLCONN))//2nd @ what its looking for.
                {
                    cmd.Parameters.AddWithValue("@CLASSNAME", newGroup);
                    cmd.Parameters.AddWithValue("@" + Group, Group);
                    cmd.ExecuteNonQuery();
                    Console.WriteLine("Database Updated...");
                }
            }
        }
        catch (Exception)
        {
            Console.WriteLine();
            Console.WriteLine("That group already exists");
            Console.ReadKey();
            SQLCONN.Close();
            goto repeat;
        }
        SQLCONN.Close();
        Console.WriteLine();
        Console.WriteLine("Which time would you like to edit for group {0}?", newGroup);
        string RESULT = Console.ReadLine();
        string ClassTime = "";
        switch (RESULT)
        {
            case "1":
                ClassTime = "09:00-09:40";
                break;
            case "2":
                ClassTime = "10:10-10:50";
                break;
            case "3":
                ClassTime = "11:00-11:40";
                break;
            case "4":
                ClassTime = "11:50-12:30";
                break;
            case "5":
                ClassTime = "12:40-13:20";
                break;
            case "6":
                ClassTime = "13:30-14:10";
                break;
            case "7":
                ClassTime = "14:20-15:00";
                break;
            case "8":
                ClassTime = "15:10-15:50";
                break;
            case "9":
                ClassTime = "16:00-16:40";
                break;
            case "10":
                ClassTime = "16:50-17:30";
                break;
            case "11":
                ClassTime = "17:40-18:20";
                break;
            case "12":
                ClassTime = "18:30-19:10";
                break;
            case "13":
                ClassTime = "19:20-20:00";
                break;
            default:
                Console.WriteLine("A time was not selected...");
                Console.WriteLine("Returning to main menu");
                Console.ReadKey();
                menu();
                break;
        }
        //Console.WriteLine("Enter the current teacher and classroom for {0}", newGroup); // DONT NEED THIS ANYMORE??
        //string teacherandclassroom = Console.ReadLine().ToUpper();
        Console.WriteLine(string.Format("Enter the new teacher and classroom number for group {0} at {1} ", newGroup, ClassTime));
        string newTeacherClassRoom = Console.ReadLine().ToUpper();
        SQLCONN.Open();
        try
        {
            using (SqlCommand cmd1 = new SqlCommand("UPDATE "+selectedDayTableToEdit+"Table SET [" + ClassTime + "] = @newValue WHERE [CLASSNAME] =@" + newGroup, SQLCONN)) //or WHERE newGroup?
            {
                cmd1.Parameters.AddWithValue("@newValue", newTeacherClassRoom); //@ can be whatever as long as its the same as the queries
                cmd1.Parameters.AddWithValue("@" + newGroup, newGroup);
                cmd1.ExecuteNonQuery();
                Console.WriteLine("Database Updated...");
            }
            SQLCONN.Close();
            Console.ReadKey();
            menu();
        }
        catch (SqlException)
        {
            SQLCONN.Close();
            Console.Clear();
            Console.WriteLine("ERROR UPDATING RECORDS....");
            Console.ReadKey();
            Console.Clear();

            if (j == 1)
            {
                menu();

            }
            else
            {
                j++;
                goto top;
            }
        }
    } 


更新
此后,我使用整数添加了 ID 主键并删除了 GC
感谢大家的评论和对我应该做什么的建议,非常感谢!
问题与check 布尔值,感谢所有指出这一点的人。

【问题讨论】:

  • 您应该尽量避免使用您足够关心并希望在未来的数据库设计中更改它的主键值。在进行更新时会产生各种令人头疼的问题。
  • 我会记住这一点@LasseV.Karlsen :) 对于这个数据库,用户不会在日常基础上更改主键值,这只是为了他们的机会做。
  • @Werdna 。 . .您应该将标识列作为主键,并将名称作为属性。您可以在名称上创建唯一约束以确保没有重复。
  • 上面的代码不应该出现上述问题。这里有一些不同的东西。 (但是,使用您计划能够修改的字段作为 PrimaryKey 确实是一种不好的做法,而且很少有道理)
  • 再次尝试check 的价值是多少?我看到您只有在遇到异常时才跳转到repeat。如果你没有得到一个怎么办? check的初始值是多少?

标签: c# sql tsql


【解决方案1】:

不是答案,但有些注释对于 cmets 来说太大了:

        SQLCONN.Open();

这条线与我有关。您应该每次都使用using 块创建一个新连接,以确保它被正确销毁。共享连接对象确实很难正确地进行,即使不是多线程也是如此。

注意:从技术上讲,关闭连接实际上并没有关闭它。它只是将其返回到连接池以供以后重用。但这不是你必须考虑的事情。


    GC.Collect();
    GC.WaitForPendingFinalizers();

不要乱用垃圾收集器。这是一种非常先进的技术,仅适用于某些形式的测试和令人难以置信的高性能应用程序。即便如此,学习如何正确地做到这一点也很困难。


   new SqlCommand("UPDATE " + selectedDayTableToEdit + "Table SET SAAT=@SAAT where SAAT=@" + Group, SQLCONN))
            {
                cmd.Parameters.AddWithValue("@Saat", newGroup);
                cmd.Parameters.AddWithValue("@" + Group, Group);
                cmd.ExecuteNonQuery();
                Console.WriteLine("Database Updated...");
            }

那真的,真的很糟糕。您正在使用任意文本创建 SQL 语句。如果有人说该组的相同是“tom; Delete FROM MyTable”,那么您将删除表中的所有内容。

除此之外,每次更改变量名都会导致它每次都创建一个新的执行计划。

   new SqlCommand("UPDATE " + selectedDayTableToEdit + "Table SET SAAT=@SAAT where SAAT=@GroupName", SQLCONN))
            {
                cmd.Parameters.AddWithValue("@Saat", newGroup);
                cmd.Parameters.AddWithValue("@GroupName", Group);
                cmd.ExecuteNonQuery();
                Console.WriteLine("Database Updated...");
            }

我也不喜欢selectedDayTableToEdit + "Table,但是当表名可以更改时,这是不可避免的。不过,最好创建一个大表以便您可以编写:

 new SqlCommand("UPDATE DatTable SET SAAT=@SAAT where SAAT=@GroupName AND DayToEdit=@Day", SQLCONN))

【讨论】:

  • 感谢@Jonathan Allen 对我将要做的事情的洞察力,我之前对 C# 控制台中的表没有太多的了解,所以它还是相当新的,谢谢你的回答您的回复,我一定会一遍又一遍地复习:)
【解决方案2】:
check = true; //weird because its working if false???

你知道奇怪的是你没有把它设置为假

if (string.IsNullOrEmpty(newGroup))
{
    newGroup = string.Format("{0}", Group);  // what is the purpose of this?
    check = true; //weird because its working if false???
}
else 
    check = false;

同意其他答案

cmd.Parameters.AddWithValue("@GroupName", Group);

不要这样做

GC.Collect();
GC.WaitForPendingFinalizers();

并且您未能检查组是否为空或为空

如果

为什么还要打开连接
if (check == false)

干净一点

    repeat:
    Console.WriteLine();
    Console.WriteLine("Which group would you like to edit?  Blank to exit.");
    string Group = Console.ReadLine().ToUpper();
    if(string.IsNullOrEmpty(Group))
        exit;  // this may be return - I forget
    Console.WriteLine("Enter {0}'s new group name if any", Group);
    string newGroup = Console.ReadLine().ToUpper();
    if(string.IsNullOrEmpty(newGroup))
        goto repeat;
    SQLCONN.Open();
    //update Group Name (SAT)
    try
    {
        using (SqlCommand cmd =
        new SqlCommand("UPDATE " + selectedDayTableToEdit + "Table SET SAAT=@NewGroup where SAAT=@SAAT", SQLCONN))
        {
            cmd.Parameters.AddWithValue("@NewGroup", newGroup);
            cmd.Parameters.AddWithValue("@Saat", Group);
            cmd.ExecuteNonQuery();
            Console.WriteLine();
            Console.WriteLine("Database Updated...");
        }
    }
    catch (Exception)
    {
        Console.WriteLine();
        Console.WriteLine("That group already exists");
    }
    finally 
    {
        SQLCONN.Close();
    }
    goto repeat;

【讨论】:

  • 为你的帮助干杯狗仔队,我最终改变了表,所以主键不会被改变,也最终保留了检查部分,我使用了“string.IsNullOrEmptry (newGroup)) “你建议的,确实很好:)
  • 而且这个答案仍然没有检查。
  • 嘿@Paparazzi,因为我使用了每个人的意见,所以如果我要使其正确,我并不太有用??
猜你喜欢
  • 2016-08-08
  • 2020-03-20
  • 1970-01-01
  • 2018-06-26
  • 2015-03-01
  • 1970-01-01
  • 2014-08-24
  • 1970-01-01
  • 2018-10-09
相关资源
最近更新 更多