C# 支持时间/更新的集合的枚举数

C# 支持时间/更新的集合的枚举数,c#,linq,database-design,C#,Linq,Database Design,我希望能够访问历史信息,以便回顾性地生成指标或了解过去某一点的情况,直到现在,我一直在存储最新的内容(例如,包含所有应用过的更新的记录)但现在我希望能够让时光倒流 在推出我自己的解决方案之前: 还有别的东西存在吗 这是标准样式吗 我可能遇到什么问题 我不希望记录的使用者能够更改它们,因此任何“更新”都应该通过存储库进行编组,它将创建包含完整内容的新记录 理想情况下,我希望将其转移到SQL后端,因此如果存在模式,我希望与它们保持距离 基本设计思想是: 定义一个接口,例如IUpdatableR

我希望能够访问历史信息,以便回顾性地生成指标或了解过去某一点的情况,直到现在,我一直在存储最新的内容(例如,包含所有应用过的更新的记录)但现在我希望能够让时光倒流

在推出我自己的解决方案之前:

  • 还有别的东西存在吗
  • 这是标准样式吗
  • 我可能遇到什么问题
我不希望记录的使用者能够更改它们,因此任何“更新”都应该通过存储库进行编组,它将创建包含完整内容的新记录

理想情况下,我希望将其转移到SQL后端,因此如果存在模式,我希望与它们保持距离


基本设计思想是:

定义一个接口,例如IUpdatableRecord:

public interface IUpdatableRecord<K>
{
    K Key { get; }
    DateTime Updated { get; }
}
公共接口IUpdatableRecord
{
K键{get;}
日期时间已更新{get;}
}
定义具有枚举功能的存储库:

public class DataRepository : IEnumerable<IUpdateableRecord<K>>
{
    // Some internal collection that allows duplicate keys
    private IList<IUpdateableRecord<K>> dataStore = ....;

    // Some enumerator overloads
    public IEnumerator<IUpdateableRecord<K>> GetEnumerator()
    {
        return dataStore.GetEnumerator();
    }

    // enumerator for contents as of a specific date-time
    public IEnumerator<IUpdateableRecord<K>> GetEnumerator(DateTime refDate)
    {
        // Group by key (so all versions of a record together)
        var groupedByKey = dataStore.GroupBy(r => r.Key);

        // Sort the keys within each group for a date/time order
        foreach ( var rec in groupedByKey )
        {
            var sorted = rec.OrderBy(r => r.Updated);

            // Ignore updates after the reference date & keep last (or default)
            var last = sorted.Where(r => r.Updated < refDate).LastOrDefault();

            // yield last record if any
            if ( last != null )
            { 
                yield return last;
            }
        }
    }

    // code for 'adding/updating' a record.
}
公共类数据存储库:IEnumerable
{
//允许复制密钥的某些内部集合
私有IList数据存储=。。。。;
//某些枚举数重载
公共IEnumerator GetEnumerator()
{
返回dataStore.GetEnumerator();
}
//截至特定日期和时间的内容的枚举数
公共IEnumerator GetEnumerator(日期时间引用日期)
{
//按键分组(以便将记录的所有版本放在一起)
var groupedByKey=dataStore.GroupBy(r=>r.Key);
//按日期/时间顺序对每组中的键进行排序
foreach(groupedByKey中的var rec)
{
var sorted=rec.OrderBy(r=>r.Updated);
//忽略参考日期后的更新并保留最后一个(或默认值)
var last=sorted.Where(r=>r.Updated< /代码> 如果您希望这个解决方案利用SQL BACKND,那么您应该考虑ADO.NET实体框架或LINQSQL.<

您的主要潜在问题是您的枚举器,因此您需要查看许多方法,检查Linq生成的SQL(这很好),并确保其有效性。

在RDBMS中有几个解决方案可以推动EMT;一种是存储给定键值的所有历史值以及“有效起始日期”和“有效截止日期”。(这通常用于数据仓库解决方案)。这会使您的查询变得非常复杂,并且对现有解决方案进行改造是一件痛苦的事情。我使用的另一种方法是保存作为现有表副本的历史表,以及一些额外的元数据列;通过强制执行所有更新过程,您可以将更改前记录写入历史记录表。对核心表的任何现有查询都可以,因为它们可以看到当前值,但是对于历史查询,您可以合并核心表和历史表(在我的例子中,通过视图)以提供LINQ对象的源


在SQL Server中,我对历史表使用单独的历史模式,以便您可以重复使用表名。

我随后发现此问题有一个名称,我想要的数据库类型是

谷歌搜索这个词显示了一些非常有用的链接,包括一本完整的(绝版)书 从这个问题中引用的是类似的


参考的书在此处以免费PDF格式提供:

您打算由谁设置更新时间?是回购协议,还是用户?请看,界面上有一个只读更新方法,因此假设它是repo。我假设存储库或其他委托类将保持更新时间-我认为历史数据的使用者不应该有能力更改内容,因此应该显示只读记录(但这个问题的其余部分是从这个问题中抽象出来的)。如果文档中说“截至”,我希望计算结果是