【问题标题】:Storing references to an object in DataTable using the "this" keyword使用“this”关键字在 DataTable 中存储对对象的引用
【发布时间】:2012-11-05 22:04:00
【问题描述】:

我有一个没有键、顺序或其他明显索引的对象集合。

我希望将有关每个对象的数据存储在 DataTable 中。我认为这样做的一种优雅方法是将引用存储在所有者列中,并使该列类型为typeof(MyClass)

但是,当我在实践中尝试这样做时,它不起作用(它说主键冲突)。事实证明,将实例放入行字段只是将“MyProgram.MyClass”写入该字段 - 可能是 toString 的输出,即使该行的类型应该是 MyClass 而不是 string

这里是一些在 LINQPad 中工作的示例代码:

void Main()
{
    // Create a table
    var table = new DataTable();

    var ownerColumn = new DataColumn("Owner", typeof(MyClass));

    var primaryKey = new[] { ownerColumn };

    table.Columns.AddRange(primaryKey);
    table.PrimaryKey = primaryKey;

    table.Columns.Add(new DataColumn("Some Data", typeof(int)) { DefaultValue = 0 });

    // Create 2 objects
    var c1 = new MyClass();
    var c2 = new MyClass();

    // Store their data in the table
    var row = table.NewRow();
    row["Owner"] = c1;
    row["Some Data"] = 1;
    table.Rows.Add(row);

    row = table.NewRow();
    row["Owner"] = c2;
    row["Some Data"] = 2;
    table.Rows.Add(row);
}

// Define other methods and classes here
class MyClass {

}

我该怎么做才能解决这个问题?我是否必须在MyClass 中创建一个id 字段,然后使用id 填写所有者列,然后确保每个对象在自己创建时收到唯一的id

【问题讨论】:

  • 您确定代码不起作用吗?查看 .NET 代码,没有理由不这样做。 row["Owner"].GetType() 的输出是什么?
  • @Knaģis 这是typeof (MyClass)。此外,它会在 LinqPad 中引发异常,除非我也错误地编译了 C# 代码。
  • 好的,所以要求是使用 MyClass 作为 DataTable 的主键?
  • @Knaģis 我想是的。我试图使用对MyClass 实例的引用作为键,这样就不能有两行指向同一个对象。
  • 添加了一个新答案,描述了使用 MyClass 作为主键所需的条件。

标签: c# ado.net reference datatable


【解决方案1】:

您必须在MyClass 上实现System.IComparable(非通用版本)接口,以便DataTable 知道如何比较列的值。如果未定义此接口,则代码回退到比较 object.ToString() 结果。

【讨论】:

  • 谢谢,这行得通!但是对于我正在尝试编程的东西, MyClass 实例具有“排序顺序”是不合逻辑的。我将该方法实现为public int CompareTo(object other) { return other == this ? 0 : 1; },但有没有更不那么老套的方法?似乎实现 IEquatable 不起作用。
  • 我建议实现 IComparable 以便它返回确定性的排序顺序,例如,使用 return other == this ? 0 : this.GetHashCode().CompareTo(other.GetHashCode())(请记住检查 null-s。原因是某些集合实际上会检查是否CompareTo 结果是有意义的(例如,检查if a > b then b must be < a
  • 谢谢,我没有想到空值或哈希码。我的问题中的问题在这一点上得到了解决,但是,我认为在你的版本中,如果两个对象的哈希值发生冲突,两个对象可以被评估为相等(不同的对象 -> 检查哈希值 -> 哈希值恰好相同 -> 哈希值比较无论如何都会返回 0 )。我的意图是MyClass.CompareTo 返回 0 如果且仅当两个引用指向同一个地方,而不仅仅是具有相同哈希值的对象。
  • 没关系,我能找到一个满意的哈希函数(其实我觉得默认的实现也很满意):stackoverflow.com/questions/1139767/object-gethashcode
【解决方案2】:

您可以使用自动增量列:

DataTable dTable = new DataTable();
DataColumn auto = new DataColumn("AutoID", typeof(System.Int32));
dTable.Columns.Add(auto);
auto.AutoIncrement = true;
auto.AutoIncrementSeed = 1;
auto.ReadOnly = true;

【讨论】:

  • 我不确定,但这不会导致标准化问题吗?具体来说,我可以有两行具有不同的“AutoID”值但相同的“所有者”,除非我将它们都设为主键,其中我的主键将变得多余。 (我在这里提出了一个单独的问题:stackoverflow.com/questions/13233088/…
猜你喜欢
  • 2013-06-11
  • 2023-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-11
  • 2020-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多