防止重复条目进入ListView / Access DB

时间:2018-07-11 16:54:08

标签: c# listview

我想将序列号扫描到一个列表视图中,该列表视图将数据存储到访问数据库中。当用户单击“提交”时,程序应存储数据或显示一条消息,指示序列号重复。这是我的代码:

这是我连接数据库的方式:

namespace Serial_Number_Checker
{
     public partial class Form1:Form
     {
         static string conString = ""
         OleDbConnection con = new OleDbConnection(conString);
         OleDbCommand cmd;
         OleDbDataAdapter adapter;
         DataTable dt = new DataTable();

这是我为列表视图创建列的方式:

    public Form1()
    {
        InitializeComponent();

        listView1.SelectedIndexChanged += new EventHandler(listView1_SelectedIndexChanged); // Adding columns to listView1

        // list view properities
        listView1.View = View.Details;
        listView1.FullRowSelect = true;

        // Add Columns
        listView1.Columns.Add("Employee #", 150);
        listView1.Columns.Add("Serial Number", 150);
        listView1.Columns.Add("Date/Time", 150);            
    }

这是“添加到listView”部分:

    // Add To ListView1
    private void populate(String employeeid, String sn, String timestamp)
    {
        // Row
        String[] row = { employeeid, sn, timestamp };

        ListViewItem item = new ListViewItem(row);

        listView1.Items.Add(item);
    }

这是检索功能:

    // Retrieve Check In
    private void retrieve()
    {
        listView1.Items.Clear();

        //Sql statement
        String sql = "Select * FROM SN_Incoming";
        cmd = new OleDbCommand(sql, con);

        //Open connection, retrieve, and fill listview1
        try
        {
            con.Open();
            adapter = new OleDbDataAdapter(cmd);

            adapter.Fill(dt);

            //Loop thru dt
            foreach (DataRow row in dt.Rows)
            {
                populate(row[0].ToString(), row[1].ToString(), row[2].ToString());
            }

            con.Close();

            //Clear datatable
            dt.Rows.Clear();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            con.Close();
        }
    }

这是“提交”按钮部分:

  private void button1_Click(object sender, EventArgs e)
{
    foreach (ListViewItem itemSelected in listView1.SelectedItems)
    {
        listView1.Items.Remove(itemSelected);
    }

    if (textBox1.Text == "")
    {
        MessageBox.Show("Please Enter A Serial Number!", "Input");
    }

    else
    {
        add(textBox1.Text);
    }


    textBox1.Text = "";
    textBox1.Focus(); // Set Focus
    textBox1.SelectionStart = textBox1.Text.Length == 0 ? 0 : textBox1.Text.Length - 1; // set text selection to end
    textBox1.SelectionLength = 0; // Set text Selection Length

    retrieve();
}

这应该是大多数代码。任何帮助。

1 个答案:

答案 0 :(得分:0)

据我所知,您想避免将重复的记录添加到ListView控件中。我将介绍防止在您的ListViewAccess Database中重复。

ListView

在将序列号添加到控件之前,我将其分配给每个Tag的{​​{1}}属性来处理。然后,为确保不添加重复项,我将使用ListViewItem作为要添加的新序列号的参考点。例如:

Tag

以上解决方案使用// Make sure you include the using statement at the top of your code file. using System.Linq; private void populate(string employeeid, string, sn, string timestamp) { ListViewItem lvi = listView1.Items.Cast<ListViewItem>() .SingleOrDefault(s => s.Tag == sn); if (lvi == null) { lvi = new ListViewItem(employeeid); lvi.SubItems.Add(sn); lvi.SubItems.Add(timestamp); lvi.Tag = sn; listView1.Items.Add(lvi); } else MessageBox.Show("Serial number supplied already exists."); } ,它代表Language Integrated Query。它是在.NET 3.5中引入的。该方法实际上是试图找到一个LINQ,其中包含ListViewItem属性,该属性的值是提供的序列号。

Tag to开始,method Cast呼叫使您可以利用SingleOrDefault可用的IEnumerable property Items不是源自ListView,而是源自IEnumerable

您可以通过实现ListViewItemCollection循环而不是利用foreach将其降低到.NET的较低级别。例如:

LINQ

数据库

由于您对数据库使用Access,因此您可以按照this指南中的说明,防止列中出现重复值(在您的情况下,这将防止重复的序列号)。本质上,您只是为希望具有唯一性的字段创建唯一索引。这是通过将字段的private void populate(string employeeid, string, sn, string timestamp) { foreach (ListViewItem lvi in listView1.Items) { if (lvi.Tag == sn) { MessageBox.Show("Serial number supplied already exists."); return; } } // We know the serial number doesn't exist, so just add the new item. ListViewItem lvi = new ListViewItem(employeeid); lvi.SubItems.Add(sn); lvi.SubItems.Add(timestamp); lvi.Tag = sn; listView1.Items.Add(lvi); } 属性设置为Indexed来完成的。

  

将字段的索引属性设置为是(无重复)

     
      
  1. 在导航窗格中,右键单击包含该字段的表,然后单击“设计视图”。
  2.   
  3. 选择要确保具有唯一值的字段。
  4.   
  5. 在“字段属性”窗格中的“常规”选项卡上,将“索引”属性设置为“是(无重复)”。
  6.   

有用点

  1. Yes表达式由编译器分解成其基本实现。例如,LINQ遍历对象集合,尝试查找满足指定条件的单个对象,然后返回结果。如果未找到对象,则返回SingleOrDefault。这是通过null循环完成的。
  2. 在大多数情况下,foreach循环实际上比使用foreach更快。在小范围内,甚至都不会注意到。但是,将必须遍历的LINQ对象的数量增加到300,000+范围内,您将有很大的不同。
  3. 此外,将所有ListViewItem对象添加到通用集合,然后再通过ListViewItem最终添加到ListView更为有效。如果我没记错的话,这是因为AddRangeAdd导致AddRange重新排序,并且如上文第2点所述,您拥有的物品越多,对性能的影响就越差。我在下面提供了这种实现的示例:

添加范围实现

ListView

代码重构

我自由地重构代码,以教会您更简单/有效的方法来实现目标。您可能需要查看以下文档:using statementstring.IsNullOrWhiteSpace()string.Empty。我会用List<ListViewItem> items = new List<ListViewItem>(); for (int i = 0; i < 50000; i++) { ListViewItem lvi = new ListViewItem($"Some kind of text {i}."); lvi.Tag = i; items.Add(lvi); } listView1.Items.AddRange(items.ToArray()); 语句提示您的一件事是,在执行块的最后部分时,它将自动关闭任何打开的连接,这是由于对象的处置所致:

  

using对象的生存期仅限于单个方法时,应在IDisposable语句中声明并实例化它。 using语句以正确的方式在对象上调用Dispose方法,并且(如前所述,当您使用它时)它也会导致对象本身在{{3 }} 叫做。在using块中,该对象为只读对象,无法修改或重新分配。

using