c# - 使用数据集的更有效方法

标签 c# .net winforms refactoring dataset

作为更新过程的一部分,我在每个Form上重复了以下代码。当页面加载时,BLL返回一个DataSet,比如

_personInfo = ConnectBLL.BLL.Person.GetPerson(personID);

我将DataSet存储在Form级别变量中,然后使用该变量检查验证/更新过程中的更改。我一次传递一行(尽管从来没有超过一行)给Function,它接受控件中的值并将其与DataSet中相应的列值进行比较。如果发现不同,则将该列设置为新值,并将名称添加到更改内容的List中。
// Load Person info
        using (var tmpPersonDT = tmpPersonDS.Tables[0])
        {
            if (tmpPersonDT.Rows.Count > 0)
            {
                foreach (DataRow row in tmpPersonDT.Rows)
                {
                    CheckPersonData(row);
                }

            }
        }

// Snippet of the CheckPersonData() that is being called....
    if (!object.Equals(row["ResidencyCountyID"], lkuResidenceCounty.EditValue))
    {
        row["ResidencyCountyID"] = lkuResidenceCounty.EditValue;
        _whatChanged.Add("ResidencyCounty");
    }

if (!object.Equals(row["ResponsibilityCountyID"], lkuResponsibleCounty.EditValue))
{
    row["ResponsibilityCountyID"] = lkuResponsibleCounty.EditValue;
    _whatChanged.Add("ResponsibilityCounty");
}

if (!object.Equals(row["HispanicOriginFlag"], chkHispanic.EditValue))
{
    row["HispanicOriginFlag"] = chkHispanic.EditValue;
    _whatChanged.Add("HispanicOriginFlag");
}

if (!object.Equals(row["CitizenFlag"], chkCitizen.EditValue))
{
    row["CitizenFlag"] = chkCitizen.EditValue;
    _whatChanged.Add("CitizenFlag");
}

if (!object.Equals(row["VeteranFlag"], chkVeteran.EditValue))
{
    row["VeteranFlag"] = chkVeteran.EditValue;
    _whatChanged.Add("VeteranFlag");
}

我想得到的答案是,这真的是解决这个问题最有效的方法吗?
如果没有其他事情,我想创建一个函数来进行比较,而不是重复30次(每个表单各不相同),但我不能完全搞清楚。我想也许我可以使用row[].itemrarray,但它只有值。我得提前知道这些东西是什么样的顺序,并保证它们不会改变。
在crud应用程序中处理数据集/数据表时,我是否遗漏了一些显而易见的东西?
juliandewitt's post below is fantastic!
我只是,现在,需要一些如何在上面使用的指导。任何人可以给我指出的链接都将不胜感激。如果你能举个例子就更好了。
使用这样的数据行有什么缺点吗?

最佳答案

看起来您正在做大量的手工工作,可以通过将控件直接数据绑定到数据集/表来减轻这些工作。数据绑定使数据源(在本例中是数据集/表)与用户界面垂直。当ui中的值发生变化时,它将更新数据源。
数据绑定是一个值得研究和测试的大课题。数据绑定到数据表/数据集时会遇到一些问题(直到当前行发生更改才会提交行更改,这在一次只处理一行的情况下很烦人——但也有解决方法)。
改写:
另一件要考虑的事情是使用业务对象来表示集合/表中的数据。orm(object relational mappers)可以为您处理这个问题,但它们是一个巨大而强大的框架,不容易掌握。它与在ui层处理数据集/表的模式完全不同,更适合于面向对象编程。数据集和表非常适合处理表格数据,但它们不适合处理实体。例如,您将处理具有诸如ishispanic和iscitizen rahtner等属性的person对象的实例,而不是基本上处理表中的单元格(不再是*mypersontable[0][“西班牙裔originflag”]…..)。
进一步:与您的问题无关,但与围绕ado.net的crud操作相关:熟悉内置在datatable/dataset中的状态跟踪是值得的。在ado.net中有很多内置功能,可以帮助这些应用程序更容易地粘合在一起,这将像您展示的那样清理大量代码。
与往常一样,rad工具有放弃对生产力控制的权衡——但是在不理解它们的情况下将它们写下来,可以保证您将花费数天的时间来编写如您所示的代码。
更重要的是:要在我之前的基础上进一步构建,当您发现可以将visual studio的数据集生成器与数据表的内置行状态跟踪结合起来,并更改数据集的跟踪时,可以很容易地在很短的时间内编写完整的crud系统。
下面是一些相关步骤的简要介绍:
建立数据库架构
在visual studio中向项目添加新的数据集项
查找服务器资源管理器(在视图下)
将SQL Server添加为数据连接
将表/存储过程/视图拖到数据集的设计器中。
右键单击Visual Studio为您生成的“TableAdapter”;转到“配置”
为数据集配置crud命令(select、insert、update、delete命令)
这样就创建了一个强类型数据集。数据集将包含一个datatable属性,该属性以用于生成数据集的table/view/storage过程命名。该表属性将包含强类型行,使您可以将该行中的单元格作为属性而不是对象数组中的非类型项进行访问。
因此,如果您生成了一个名为mydbtables的新数据集,其中有一个名为tblcustomer的表,该表包含一些列,如customerid、name等……然后你可以这样处理:
这是一个完整的示例,展示了一些用于crud工作的常用方法——在tableadapter类中查看方法和特殊性

    public void MyDtDemo()
    {
        // A TableAdapter is used to perform the CRUD operations to sync the DataSet/Table and Database
        var myTa = new ClassLibrary4.MyDbTablesTableAdapters.tblCustomersTableAdapter();
        var myDataSet = new MyDbTables();

        // 'Fill' will execute the TableAdapter's SELECT command to populate the DataTable
        myTa.Fill(myDataSet.tblCustomers);

        // Create a new Customer, and add him to the tblCustomers table
        var newCustomer = myDataSet.tblCustomers.NewtblCustomersRow();
        newCustomer.Name = "John Smith";
        myDataSet.tblCustomers.AddtblCustomersRow(newCustomer);

        // Show the pending changes in the DataTable
        var myTableChanges = myDataSet.tblCustomers.GetChanges();

        // Or get the changes by change-state
        var myNewCustomers = myDataSet.tblCustomers.GetChanges(System.Data.DataRowState.Added);

        // Cancel the changes (if you don't want to commit them)
        myDataSet.tblCustomers.RejectChanges();

        // - Or Commit them back to the Database using the TableAdapter again
        myTa.Update(myDataSet);
    }

另外,还要注意数据集和数据表的rejectChanges()和acceptChanges()方法。它们基本上告诉您的数据集它没有任何更改(通过拒绝所有更改或“提交”所有更改),但请注意,调用acceptChanges()然后尝试执行更新将不会有任何效果--数据集已丢失任何更改的跟踪,并假定它是数据库的准确反映。
甚至更多!下面是一个重新编写的示例版本,显示了一些rowstate跟踪特性,假设您已经按照我的步骤创建了强类型数据集/表/行
    public void CheckRows()
    {
       MyPersonDS tmpPersonDS = new MyPersonDS();

        // Load Person info
       using (var tmpPersonDT = tmpPersonDS.PersonDT)
       {
           foreach (MyPersonRow row in tmpPersonDT.Rows)
           {
               CheckPersonData(row);
           }
       }

    }

    public void CheckPersonData(MyPersonRow row)
    {
        // If DataBinding is used, then show if the row is unchanged / modified / new...
        System.Diagnostics.Debug.WriteLine("Row State: " + row.RowState.ToString());

        System.Diagnostics.Debug.WriteLine("Row Changes:");
        System.Diagnostics.Debug.WriteLine(BuildRowChangeSummary(row));

        // If not DataBound then update the strongly-types Row properties
        row.ResidencyCountyID = lkuResidencyCountyId.EditValue;


    }

    public string BuildRowChangeSummary(DataRow row)
    {
        System.Text.StringBuilder result = new System.Text.StringBuilder();

        int rowColumnCount = row.Table.Columns.Count;
        for (int index = 0; index < rowColumnCount; ++index)
        {
            result.Append(string.Format("Original value of {0}: {1}\r\n", row.Table.Columns[index].ColumnName, row[index, DataRowVersion.Original]));
            result.Append(string.Format("Current  value of {0}: {1}\r\n", row.Table.Columns[index].ColumnName, row[index, DataRowVersion.Current]));

            if (index < rowColumnCount - 1) { result.Append("\r\n"); }
        }

        return result.ToString();
    }

关于c# - 使用数据集的更有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1273197/

相关文章:

C# 如何根据之前从代码创建的面板的位置创建面板?

c# - 在我的应用程序中嵌入控制台应用程序

.net - 从 vb.net 中的文件中提取值

c# - 当结构包含整数数组时,如何避免在 PInvoke 编码期间进行复制?

c# - C# 中的基本数据结构

C# - 将 TextBox 绑定(bind)到整数

winforms - "BindingSource cannot be its own data source"- 尝试从另一个类中的方法重置绑定(bind)源时出错

c# - 如何访问已编译的.NET 程序集的 MSIL 代码?

c# - 使用 "await"时,运行时如何知道何时生成线程?

c# - 是什么导致我的 c# WinForms 应用程序卡住/挂起?