1

私は大学のプロジェクトの自動登録に取り組んでいます。RFID スキャナーを使用して学生のタグ ID をスキャンし、それを使用してデータベースにクエリを実行し、結果を DataGridView に表示します。

ランタイム プロセスは次のとおりです。

  • ユーザーがタグをスキャンします (RFID_DataReceived ハンドラーが起動してタグを読み取り、実行してタグがDB のテーブルにTagExistsQuery()存在するかどうかを確認します)Student

  • タグがデータベースに存在する場合は、実行AttendanceQuery()してタグを特定の講義と照合し、結果を DGV に表示します

  • タグが DB に存在しない場合は、エラー メッセージを表示します。

私の問題はAttendanceQuery()、同じレコードが複数回 (正確には 16 回) 生成されることです。これは何日もの間私を夢中にさせています。お役に立てれば幸いです。

私のコードは次のとおりです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;

namespace AutoReg
{
    public partial class RoomActiveSession : Form
    {
        // Create the serial port with basic settings
        public SerialPort port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);

        public int tagNo;


        public RoomActiveSession()
        {
            InitializeComponent();

            //Attach a method to be called when there is data waiting in the port's buffer
            port.DataReceived += new SerialDataReceivedEventHandler(RFID_DataReceived);

            //Begin communications
            port.Open();
        }


        public void RFID_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            while (port.ReadChar() != 2) ;

            int v = 0;
            port.ReadChar(); // drop 1st 2 bytes - we actually only read the lower 32-bits of the code
            port.ReadChar();

            for (int i = 7; i >= 0; i--)
            {
                int c = port.ReadChar(); // a ascii hex char
                int part = c - '0';

                // test if 'Alpha'

                if (part > 9) part -= 7;     // Quick & dirty !


                v |= part << (i * 4);
            }

            for (int i = 0; i < 5; i++)
            {
                port.ReadChar();
            }

            tagNo = v;


            this.Invoke(new MethodInvoker(delegate()
            {

                TagExistsQuery();
            }

            ));

        }

        //SQL query that checks if the scanned tag already exists in the "Student" table
        public void TagExistsQuery()
        {
            DataTable queryResult = new DataTable();
            string ConnStr = "Data Source=DUZY;Initial Catalog=AutoRegSQL;Integrated Security=True";

            SqlConnection MyConn = new SqlConnection(ConnStr);
            MyConn.Open();

            string query = @"SELECT TagID" +
               " FROM Student " +
               " WHERE TagID = @tagNo ";

            SqlCommand command = new SqlCommand(query, MyConn);

            command.Parameters.Add("tagNo", SqlDbType.Int).Value = tagNo;


            SqlDataAdapter adapter = new SqlDataAdapter(command);

            adapter.Fill(queryResult);

            if (queryResult.Rows.Count == 0)
            {
                MessageBox.Show("Unable to match scanned tag with the Student database. Please contact help desk for assistance");
                MyConn.Close();
            }
            else
            {
                MyConn.Close();
                AttendanceQuery();

            }

        }

        //SQL query that finds the current sessionID for the given tagID by comparing curent date/time with date/time saved in DB and display result in DGV
        public void AttendanceQuery()
        {
            DataTable queryResult = new DataTable();

            string ConnStr = "Data Source=DUZY;Initial Catalog=AutoRegSQL;Integrated Security=True";

            DateTime TimePlus = DateTime.Now.AddMinutes(30);
            string Plus30Min = TimePlus.ToString("hh:mm tt");

            SqlConnection MyConn = new SqlConnection(ConnStr);
            MyConn.Open();


            string query = @"SELECT s.TagID, se.SessionID, '" +
               DateTime.Now +
               "' AS ScanningTime " +
               " FROM (((Student s " +
               " LEFT JOIN [CourseID-ModuleID] cm ON s.CourseID = cm.CourseID) " +
               " LEFT JOIN [ModuleID-SessionID] ms ON ms.ModuleID = cm.ModuleID) " +
               " LEFT JOIN [Session] se ON ms.SessionID = se.SessionID) " +
               " WHERE s.TagID = @tagNo " +
               " AND se.SessionDate = cast(getdate() as date) " +
               " AND se.SessionTimeStart <= @Plus30Min " +
               " AND se.SessionTimeEnd >= @Plus30Min ";

            SqlCommand command = new SqlCommand(query, MyConn);

            command.Parameters.Add("tagNo", SqlDbType.Int).Value = tagNo;
            command.Parameters.Add("Plus30Min", SqlDbType.VarChar).Value = Plus30Min;

            SqlDataAdapter adapter = new SqlDataAdapter(command);

                adapter.Fill(queryResult);

                if (queryResult.Rows.Count == 0)
                {
                    MessageBox.Show("Unable to register student " + tagNo);
                    MyConn.Close();
                }
                else
                {

                    SetDataSouce(queryResult);
                    MyConn.Close();
                }
        }


        private void button1_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }


        public void SetDataSouce(object source)
        {
            dataGridView1.DataSource = source;
        }


     }
}

編集:

これまでの貢献に感謝します。

あなたの多大な助け(@ user123などに感謝)により、次のコードでもSSMSで16個のレコードが生成されることを確認できました。

DECLARE @Plus30Min TIME, @tagNo INT
SET @Plus30Min = DATEADD(MINUTE,30,GETDATE())
SET @tagNo = 4820427

SELECT s.TagID, se.SessionID
FROM (((Student s
LEFT JOIN [CourseID-ModuleID] cm ON s.CourseID = cm.CourseID)
LEFT JOIN [ModuleID-SessionID] ms ON ms.ModuleID = cm.ModuleID)
LEFT JOIN [Session] se ON ms.SessionID = se.SessionID)
WHERE s.TagID = @tagNo
AND se.SessionDate = cast(getdate() as date)
AND se.SessionTimeStart <= @Plus30Min
AND se.SessionTimeEnd >= @Plus30Min

LEFT JOIN の代わりに INNER JOIN を使用しても、1 ではなく 16 が生成されます。

編集 CD:

問題が解決しました。テーブルの 1 つに複数のレコードがあることに気付きました。皆様のご協力、ご指摘、お時間を割いていただき、誠にありがとうございました。私のような初心者は SO と喜んで助けてくれるあなたのようなユーザーがいることを幸運に思います。ありがとうございました!

編集 CD2:

テーブルから複数のレコードを削除するとCourseID-ModuleID、生成されるレコードが 16 から 4 に制限されるだけなので、進歩はありますが、完全ではありません。LEFT JOIN の代わりに INNER を使用してみましたが、結果は同じままです。

EDIT CD3: 再びテーブルをチェックし、いくつかのダミー エントリがそこに残っていました。あなたはまだ素晴らしいですが、私はまだプログラミングが苦手です:)

4

3 に答える 3

0
  1. tagid がユーザー テーブルで一意であることを確認します。

  2. クエリ結果にse.SessionTimeStartとを追加します。se.SessionTimeEnd過去にいくつかの終わりのないセッションが開始されたのではないかと思います。

  3. これが 12 時間制ではなく 24 時間制であることを確認してください。

    string Plus30Min = TimePlus.ToString("hh:mm tt");

于 2013-08-12T14:24:01.963 に答える
0

学生ごとに複数のコース、コースごとに複数のモジュール、モジュールごとに複数のセッションを持つことができるため、1 行ではなく 16 行になると思います。結合を逆にすると、1 つの行が得られるはずです (学生の LEFT JOIN セッション LEFT JOIN モジュール LEFT JOIN コース。コースは複数のモジュールであり、その逆ではありません)。ただし、たとえばセッションがない学生の行を取得します。

あなたが本当に使いたかったのはINNER JOINだと思います。

また、行が 0 を超える場合に選択してカウントする代わりに、SQL 'EXISTS' を使用できます。

于 2013-08-12T13:52:43.503 に答える