2012-02-17 59 views
0

假设您需要在由几列(如关系数据库)形成的表格中存储一些值:例如,第一列为int,第二列为string,第三列为DateTime等。如何实现一个表格?

如果一列或多列与主键相似,那么我们可以使用IDictionary,其中Key将是充当主键的字段集合。其余的字段代表Value。在这种情况下,我可以创建一个或两个类/结构。例如,如果主键是一个简单的现有类型,我们只需要创建一个类/结构如下所示:

public class MyValue 
{ 
    public int Field1; 
    public double Field2; 
    public string Field3; 
} 

字典可能是一个Dictionary<int, MyValue>,而表可以是以下。

public class MyTable 
{ 
    private Dictionary<int, MyValue> _table; 
    ... 
} 

显然,根据本申请的域可能存在用于上述领域范围和/或有效性的规则:例如,Field1可能必须为正,等等...

作为我可以设计MyValue类的第一个选择,以便引发一些例外,以识别“违反规则”。但也许这种方法可能会过度,特别是如果MyValue类只在内部使用到MyTable:在这种情况下,我将编写类似以下的代码并在MyTable类中处理有效性错误:即MyTable类在插入它们之前检查数据字段进入字典,所以MyValue将是一个“愚蠢的”类...

namespace MyNamespace 
{ 
    class MyValue 
    { 
     // only public fields 
    } 

    public class MyTable 
    { 
     private Dictionary<int, MyValue> _table; 
     ... 

     public void Add(int key, int field1, double field2, string field3) 
     { 
      // some code to check validity range for fields 
      ... 
     } 
    } 
} 

是这个解决方案是否正确?或者我应该避免这种方法?我应该总是以完整地定义一个类/结构(例外处理,EqualsGetHashCode方法?

+2

这是如此令人难以置信的广泛我甚至不知道从哪里开始。 – cadrell0 2012-02-17 21:45:31

+0

是的,这是有效的解决方案。 – 2012-02-17 21:46:30

+0

你有没有关于.NET的一些设计准则(关于这个问题)的一些链接? – enzom83 2012-02-17 23:16:40

回答

2

我会让值检查自己的一致性。如果将字段实现为属性,则setter可以执行检查并引发异常,例如值超出范围。

我也会建议一个更灵活的方法。定义表格记录必须实现的接口

public interface IRecord<PK> 
{ 
    PK ID { get; } 
} 

记录必须有一个ID,它将用作主键。我们使用通用主键类型PK

现在,您可以定义值类这样

public class MyValue : IRecord<int> 
{ 
    private int _field1; 
    public int Field1 
    { 
     get { return _field1; } 
     set 
     { 
      if (value < 0 || value > 1000) { 
       throw new ArgumentException("Value of 'Field1' must be between 0 and 1000"); 
      } 
      _field1 = value; 
     } 
    } 

    public double Field2; 

    #region IRecord<int> Members 

    public int ID { get { return Field1; } } 

    #endregion 
} 

正如你所看到的,它实现了IRecord<int>,并返回Field1IDField1检查传递给它的值。如果主键由多个字段组成,则可以使用类似Tuple(.NET 4.0)的类型作为主键类型。像IRecord<Tuple<int,double>>

现在你可以定义一个通用的表

public class Table<T, PK> 
    where T : IRecord<PK> 
{ 
    private Dictionary<PK, T> _table = new Dictionary<PK, T>(); 

    public void Add(T item) 
    { 
     _table.Add(item.ID, item); 
    } 
} 

你可以这样定义

public class MyTable : Table<MyValue, int> 
{ 
} 

更新特定表:

或者,你可以让记录的实施明显错误处理

public interface IRecord<PK> { 
    PK ID { get; } 

    bool IsValid { get; } 
    string[] Errors { get; } 
} 
4

你所做的一切看起来过于复杂,脆,最终将导致可维护性的恶梦。

我会说你有两个选择

选择一个:。使用一个DataTable它没有通过一个实际的数据库进行备份,你可以定义它的布局在运行时(包括列定义)

选项二:定义一个实现您的“记录”逻辑的类。定义一个Collection来保存这个类。使用LINQ来为你需要的任何东西“查询”集合。

这两个选项之间的主要区别是DataTable在您可以使用的规则类型中非常有限。选项2,OTOH,可以让你准确地建立你想要的。

+0

_定义一个实现你的“记录”逻辑的类。基本上这个类应该是一个简单的公共字段的“集合”:它确切吗? – enzom83 2012-02-17 23:25:55

+0

+1。 *为什么*永远考虑这样的事情?没有数据库后端?研究关系数据库完整性和业务规则的统一领域理论?即使如此,为什么要重新发明轮子? – radarbob 2012-02-20 19:55:07