C# 表示由两个外键索引的表的OOP数据结构

C# 表示由两个外键索引的表的OOP数据结构,c#,wpf,oop,.net-4.0,C#,Wpf,Oop,.net 4.0,我的任务是将“表驱动”程序转换为面向对象的程序。过去,一切都是通过在内存中创建大型表、添加和删除行和列以及将所有内容解析为字符串来完成的。这太糟糕了。这些表直接反映了存储所有内容的底层数据库的结构 对于这个问题,我有层对象,大约有100个属性,我有事件对象,大约还有20个属性。然后,我为每个层/事件对计算了大约10个值。这些表存储为第三个表,外键指向其他每个表 我想创建一个适当的面向对象类来存储这些数据,并像在字典中一样快速访问值 我的第一个想法是将结果编入词典索引,但我觉得它的使用是不直观的:

我的任务是将“表驱动”程序转换为面向对象的程序。过去,一切都是通过在内存中创建大型表、添加和删除行和列以及将所有内容解析为字符串来完成的。这太糟糕了。这些表直接反映了存储所有内容的底层数据库的结构

对于这个问题,我有
对象,大约有100个属性,我有
事件
对象,大约还有20个属性。然后,我为每个
层/事件
对计算了大约10个值。这些表存储为第三个表,外键指向其他每个表

我想创建一个适当的面向对象类来存储这些数据,并像在字典中一样快速访问值

我的第一个想法是将结果编入词典索引,但我觉得它的使用是不直观的:

struct EventLayerResult { Decimal sum = 0; Long events = 0; Decimal average; ...}
//Performing Calculations
Dictionary<Tuple<Event,Layer>, EventLayerResult> _EventLayerResults ...;
foreach(Event evt in _Events)
    foreach(Layer lyr in _Layers)
        EventLayerResult elr = newLayerLosses[Tuple.Create(evt, lyr)];
        elr.sum += currentValue;
        elr.events += 1;
        elr.average += elr.Sum/elr.Events;
        etc...
//Using results
EventLayerResult temp = _EventLayerResults.TryGetValue(Tuple.Create(evt, lyr))
someLoss = temp == null ? 0 : temp.expectedLoss;
我还认为,对这样一个结构中所包含的全部结果清单进行约束是不可能的

我最后的想法(我认为最接近我必须使用的解决方案)是一个简单的对象/结构集合,其中包含我需要引用的所有字段:

class EventLayerResult { Event oevent; Layer layer; Decimal sum; Long events...}
ObservableCollection<EventLayerResult> _EventLayerResults = ....
_EventLayerResults.Add( new EventLayerResult(){ oevent = evt, layer = lyr } );
class EventLayerResult{Event oevent;Layer-Layer;十进制和;长事件…}
ObservableCollection\u EventLayerResults=。。。。
_添加(新的EventLayerResult(){oevent=evt,layer=lyr});
这非常容易绑定,但问题是此集合上没有“索引”。我正在寻找O(Nevts*Nlyrs)时间,以便稍后查找特定的事件/层结果,除非我开始添加所有这些额外的行李,如监视集合添加事件并在字典中索引集合项的自定义包装器类等


我无法想象其他人每次想要将由两个外键索引的简单表转换为对象模型时都会经历所有这些。是否有一种我不知道的标准方法或数据结构可以使此类数据集易于使用?

到目前为止,我提出的最佳解决方案是使用字典将集合和索引封装在外键上,就像我在OP中建议的那样。尽管如此,似乎需要做很多工作:

public class EventGroupIDLayerTuple : Tuple<Int32, Layer>
{
    public EventGroupIDLayerTuple(Int32 EventGroupID, Layer Layer) : base(EventGroupID, Layer) { }
    public Int32 EventGroupID { get { return this.Item1; } }
    public Layer Layer { get { return this.Item2; } }
}
public class EventGroupLayerResult
{
    public Int32 EventGroupID { get; set; }
    public Layer Layer { get; set; }
    //Computed Values
    public Decimal Sum { get; set; }
    public Decimal Average { get; set; }
    //...
}

/// <summary>ObservableCollection of computed EventGroup/Layer results that are also indexed
/// in a dictionary for rapid retrieval.</summary>
public class EventGroupLayerResultCollection : ObservableCollection<EventGroupLayerResult>
{
    Dictionary<EventGroupIDLayerTuple, EventGroupLayerResult> _Index = 
        new Dictionary<EventGroupIDLayerTuple,EventGroupLayerResult>();

    public EventGroupLayerResultCollection() : base() { }

    /// <summary>Will return the result for the specified eventGroupID/Layer
    /// combination, or create a new result and return it.</summary>
    public EventGroupLayerResult this[Int32 eventGroupID, Layer layer]
    {
        get
        {
            EventGroupLayerResult retval;
            if( !_Index.TryGetValue(new EventGroupIDLayerTuple(eventGroupID, layer), out retval) )
            {
                retval = new EventGroupLayerResult() { EventGroupID = eventGroupID, Layer = layer };
                this.Add(retval);
            }
            return retval;
        }
    }

    public bool Contains(Int32 eventGroupID, Layer layer)
    {
        return _Index.ContainsKey(new EventGroupIDLayerTuple(eventGroupID, layer));
    }

    #region Index Maintenance
    protected override void ClearItems()
    {
        _Index.Clear();
        base.ClearItems();
    }
    protected override void InsertItem(int index, EventGroupLayerResult item)
    {
        _Index.Add(new EventGroupIDLayerTuple(item.EventGroupID, item.Layer), item);
        base.InsertItem(index, item);
    }
    protected override void RemoveItem(int index)
    {
        _Index.Remove(new EventGroupIDLayerTuple(this[index].EventGroupID, this[index].Layer));
        base.RemoveItem(index);
    }
    protected override void SetItem(int index, EventGroupLayerResult item)
    {
        _Index.Remove(new EventGroupIDLayerTuple(this[index].EventGroupID, this[index].Layer));
        _Index.Add(new EventGroupIDLayerTuple(item.EventGroupID, item.Layer), item);
        base.SetItem(index, item);
    }
    #endregion
}
同时仍然允许我轻松地将集合绑定到UI


不过,更好的解决方案还是值得的,因为我必须重写一系列可观察的收集方法才能做到这一点。

我可能遗漏了一些东西,但你不能只创建域实体,然后在数据层中使用ORM(或滚动你自己的)吗?@BobHorn ORM只会生成类似于我的第三个示例的东西,除非使用外键,而不是它们引用的对象的实际引用。它无法解决第三个示例的问题,即无法在不到O(n)的时间内根据索引查找值。
public class EventGroupIDLayerTuple : Tuple<Int32, Layer>
{
    public EventGroupIDLayerTuple(Int32 EventGroupID, Layer Layer) : base(EventGroupID, Layer) { }
    public Int32 EventGroupID { get { return this.Item1; } }
    public Layer Layer { get { return this.Item2; } }
}
public class EventGroupLayerResult
{
    public Int32 EventGroupID { get; set; }
    public Layer Layer { get; set; }
    //Computed Values
    public Decimal Sum { get; set; }
    public Decimal Average { get; set; }
    //...
}

/// <summary>ObservableCollection of computed EventGroup/Layer results that are also indexed
/// in a dictionary for rapid retrieval.</summary>
public class EventGroupLayerResultCollection : ObservableCollection<EventGroupLayerResult>
{
    Dictionary<EventGroupIDLayerTuple, EventGroupLayerResult> _Index = 
        new Dictionary<EventGroupIDLayerTuple,EventGroupLayerResult>();

    public EventGroupLayerResultCollection() : base() { }

    /// <summary>Will return the result for the specified eventGroupID/Layer
    /// combination, or create a new result and return it.</summary>
    public EventGroupLayerResult this[Int32 eventGroupID, Layer layer]
    {
        get
        {
            EventGroupLayerResult retval;
            if( !_Index.TryGetValue(new EventGroupIDLayerTuple(eventGroupID, layer), out retval) )
            {
                retval = new EventGroupLayerResult() { EventGroupID = eventGroupID, Layer = layer };
                this.Add(retval);
            }
            return retval;
        }
    }

    public bool Contains(Int32 eventGroupID, Layer layer)
    {
        return _Index.ContainsKey(new EventGroupIDLayerTuple(eventGroupID, layer));
    }

    #region Index Maintenance
    protected override void ClearItems()
    {
        _Index.Clear();
        base.ClearItems();
    }
    protected override void InsertItem(int index, EventGroupLayerResult item)
    {
        _Index.Add(new EventGroupIDLayerTuple(item.EventGroupID, item.Layer), item);
        base.InsertItem(index, item);
    }
    protected override void RemoveItem(int index)
    {
        _Index.Remove(new EventGroupIDLayerTuple(this[index].EventGroupID, this[index].Layer));
        base.RemoveItem(index);
    }
    protected override void SetItem(int index, EventGroupLayerResult item)
    {
        _Index.Remove(new EventGroupIDLayerTuple(this[index].EventGroupID, this[index].Layer));
        _Index.Add(new EventGroupIDLayerTuple(item.EventGroupID, item.Layer), item);
        base.SetItem(index, item);
    }
    #endregion
}
eventGroupLayerResults[evt.GroupID, lyr].Sum += value;