C# 如何处理(国家/地区)代码列表中不推荐的值

C# 如何处理(国家/地区)代码列表中不推荐的值,c#,.net,vb.net,database-design,C#,.net,Vb.net,Database Design,假设我们有一个所有国家的代码列表,包括它们的国家代码。国家/地区代码是国家/地区表的主键,在数据库的许多地方用作外键。在我的应用程序中,国家通常在多个表单上显示为下拉列表 过去存在的一些国家已经不复存在,例如,国家代码为SCG的国家 我有两个目标: 不允许用户使用这些旧值(因此在插入数据时,这些值在下拉列表中不可见) 用户应该仍然能够(只读)打开旧内容,在这种情况下,不推荐的值应该在下拉列表中可见 我看到两种选择: 将不推荐使用的值重命名,例如从“CountryName”重命名为“!!!”

假设我们有一个所有国家的代码列表,包括它们的国家代码。国家/地区代码是国家/地区表的主键,在数据库的许多地方用作外键。在我的应用程序中,国家通常在多个表单上显示为下拉列表

过去存在的一些国家已经不复存在,例如,国家代码为SCG的国家

我有两个目标:

  • 不允许用户使用这些旧值(因此在插入数据时,这些值在下拉列表中不可见)
  • 用户应该仍然能够(只读)打开旧内容,在这种情况下,不推荐的值应该在下拉列表中可见
我看到两种选择:

  • 将不推荐使用的值重命名,例如从“CountryName”重命名为“!!!”!!!!!国名'。这种方法最容易实现,但有明显的缺点
  • 将IsActive列添加到Countries表中,并对所有不推荐使用的值将其设置为false,对所有其他值将其设置为true。在用户可以插入数据的所有窗体上,仅显示活动的值。在只读表单上,我们可以显示所有值(包括不推荐的值),因此用户将能够显示旧数据。但是在我的一些表单上,用户还应该能够编辑数据,这意味着不推荐的值应该对他隐藏。这意味着,每个dropbox都应该具有如下初始化逻辑:如果显示的数据是只读的,则在dropbox中包含不推荐的值,如果数据也用于编辑,则将其排除。但这是一项大量的工作,而且容易出错

还有其他想法吗?

您可以使用CollectionViewSource进行筛选,也可以创建一个公共枚举表,使用LINQ筛选完整列表

LINQ FieldDef.DispSearch为激活状态。IEnumerable的性能略好于List

public IEnumerable<FieldDefApplied> FieldDefsAppliedSearch
{
    get
    {
        return fieldDefsApplied.Where(df => df.FieldDef.DispSearch).OrderBy(df => df.FieldDef.DispName);
    }
}
public IEnumerable FieldDefsAppliedSearch
{
得到
{
返回fieldDefsApplied.Where(df=>df.FieldDef.DispSearch.OrderBy(df=>df.FieldDef.DispName);
}
}

为什么您仍然希望显示(例如)带有旧国家代码的客户地址?
如果我理解正确,您目前仍然有“地址”记录,仍然指向“塞尔维亚和黑山”。我想如果你解决了这个问题,你现在的问题就不存在了

术语“国家”可能有点误导:并非ISO 3166中的所有“国家”实际上都是独立的。相反,其中许多是地理上独立的领土,在法律上是其他国家的一部分或附属领土

还请注意,“撤销的国家代码”保留5年,这意味着5年后可以重新使用。因此,对我来说,不再使用国家代码本身作为主键是有意义的,特别是如果出于历史原因,您需要追溯以前的国家代码

那么为什么不创建指向新国家id的“撤回”字段/表格呢。您仍然可以检查(例如,在sql中,因为您已经在使用一个表)该字段是否为空,如果需要,还可以不进行真/假检查

在我看来:“国家”代码可能会改变,国家可能会合并,国家可能会分裂

如果国家/地区发生更改或合并,您可以通过简单的查询更新您的地址记录

如果国家存在分歧,您需要一种方法来确定哪个地址是哪个国家的一部分。 您可以使用一些自动化系统来完成这项工作(并为此撰写长篇书籍)。

(当它是一个类似论坛的站点时),您可以要求仍然有一个撤回国家的用户在其帐户中指向多个备选方案,在登录时更新其国家条目,他们只能从撤回字段中指定的新国家列表中进行选择

想想这个简化的国家/地区表设置:

id  cc  cn                     withdrawn
1   DE  Germany
2   CS  Serbia and Montenegro  6,7
3   RH  Southern Rhodesia      5
4   NL  The Netherlands        
5   ZW  Zimbabwe
6   RS  Serbia
7   ME  Montenegro
在本例中,国家id为3的地址记录将通过对国家id为5的查询进行更新,无需用户交互(或其他解决方案)。
但是,指定国家id 2的地址记录将被要求选择国家id 6或7(当然是在提供给使用国家名称的用户的文本中),或者被选择在其上执行自定义自动更新例程

另外请注意:“撤回”是一个重复组,因此您可以/应该将其放入单独的表中

在您的场景中实现此想法(无需停机):

  • sql语句来构建一个以数字id作为主键的新国家/地区表
  • sql语句,用新字段“country id”更新地址记录,并用新国家表中的国家id填充此字段,该国家id对应于该记录的地址字段中指定的国家代码
  • (sql语句)创建撤回的表,并在其中填充正确的数据
  • 然后重写为表单提供数据的sql语句
  • 添加检查和“要求用户更新国家/地区”-例行程序
  • 让新表格上线
  • 等待/查看意外错误
  • 从“地址”表中删除旧的国家/地区表和(现在未使用的)国家/地区代码列

我很好奇其他专家对这个想法的看法

我经常处理这种情况,并使用“活动”标志来解决问题,正如您所描述的那样。当我用值填充下拉列表时,我只加载“活动”数据并包含多达1个不推荐的值,但仅当它正在使用时。(即,如果我查看的是个人记录,而此人的国家/地区已弃用,则该国家/地区将与活动国家/地区一起包含在下拉列表中。我以只读和编辑模式执行此操作,因为在我的情况下,如果个人记录(例如)如果列出了不推荐使用的国家/地区,他们可以继续使用,但一旦他们将其更改为非不推荐使用的国家/地区,然后将其保存,他们就无法继续使用
    protected void LoadSourceDropdownList(bool AddingNewRecord, int ExistingCode)
    {
        using (Entities db = new Entities())
        {
            if (AddingNewRecord) // when we are adding a new record, only show 'active' items in the drop-downlist.
                ddlSource.DataSource = (from q in db.zLeadSources where (q.Active == true) select q);

            else // for existing records, show all active items AND the current value.
                ddlSource.DataSource = (from q in db.zLeadSources where ((q.Active == true) || (q.Code == ExistingCode)) select q);

            ddlSource.DataValueField = "Code";
            ddlSource.DataTextField = "Description";
            ddlSource.DataBind();

            ddlSource.Items.Insert(0, "--Select--");
            ddlSource.Items[0].Value = "0";
        }
    }