【问题标题】:History tables in .NET MVC code first approach?.NET MVC 代码优先方法中的历史表?
【发布时间】:2012-08-31 07:03:16
【问题描述】:

我需要使用代码优先方法跟踪 MVC .NET 应用程序中某些数据库对象的更改历史记录。

历史表的含义如下: http://database-programmer.blogspot.de/2008/07/history-tables.html

如果我自己编写 SQL 查询,我会使用历史表。但在代码优先的方法中,会生成 SQL……我想坚持这种范式。

目标是一个结构,其中包含更改/删除条目的所有“旧”修订以及一些附加信息(例如时间戳、更改它的用户......)

有什么想法吗?

问候, 斯蒂芬

更具体地说 - 这是一些代码示例:

public class Node {
 public int NodeID { get; set; }

 public string? data { get; set; }  // sample data
}


public class NodeHistory {
  public int NodeID { get; set; }
  public string? data { get; set; }

  public int UserID { get; set; }
  public DataTime timestamp { get; set; }
}

我需要一些“框架”帮助,以便能够在更改持久化时向 NodeHistory 添加条目以表节点结构。

这意味着:仅仅覆盖 set-method 不是一个解决方案,因为它也会创建一个条目,如果对“节点”的更改没有在最后保持(例如角色回退)。

【问题讨论】:

  • 不要觉得自己被生成的 SQL 卡住了。修改数据层以满足您的需求并没有什么坏处,尤其是当业务层中没有表示时。
  • 我添加了一些代码,它解释了问题所在。

标签: c# asp.net-mvc database ef-code-first


【解决方案1】:

这确实是您应该使用触发器执行的操作。是的,您必须为其编写一些 sql,但是无论更新如何发生,手动或通过其他方式,都会更新历史记录。

【讨论】:

  • 我认为不可能存储“userid”(修改它的人),只能使用触发器。我至少需要一个存储过程来移交此参数,但这会使所有“代码优先”范式变得无用。因为我必须自己编写数据库访问函数,对吧?
  • @StefanK。 - 这取决于应用程序是否使用 Windows 身份验证运行,以及您对数据库使用广告身份验证。如果他们在 Sql management studio 中编辑了记录,你怎么知道他们?
  • 该应用程序只是一个 Web 前端。有效用户只为应用程序所知。我可以编写一个存储过程来对表进行写访问...
  • @StefanK。 - 是否“只是一个前端”并不重要,重要的是您使用的身份验证类型。
  • 什么...它绝对不使用 Windows 身份验证来验证用户(=主体,需要记录的内容)本身。但我们将使用它来验证应用程序用户(应用程序在其下运行)以访问数据库。
【解决方案2】:

我认为对我来说最好的方法是使用存储库模式,并在您认为适合保留历史记录的 Node 对象上的每个操作上插入 NodeHistory 表。

编辑:一些代码

public class NodeRepository{
    public Node EditNode(Node toEdit, int userId){
        using(new TransactionScope())
        {            
            //Edit Node in NodeContext like you would anyway without repository
            NodeContext.NodeHistories.Add(new NodeHistory(){//initialise NodeHistory stuff here)
            NodeContext.SaveChagnes();
        }
    }
}
public class NodeContext:DbContext{
    public DbSet<Node> Nodes{get;set;}
    public DbSet<NodeHistory> NodeHistories{get;set;}
}

如果您正在寻找比这更简单的东西,那么我不知道它可能是什么。

【讨论】:

  • 查找“存储库模式”。乍一看,这看起来像我需要的......如果它解决了问题,会让你知道。有什么好的教程可以推荐吗?
  • 我有另一个很好的教程,如果我现在找不到,我会在这里发布:blogs.msdn.com/b/adonet/archive/2009/06/16/…
  • 嗯,似乎“存储库模式”有点太复杂而无法理解。它应该是一个易于理解的解决方案,因为不仅我必须理解它,而且其他人必须管理该代码(我没有任何解释,除了源代码中的一些 cmets)。
  • 有没有办法派生 DbSet 的子类,它可以正常执行所有操作,但可以对事件做出反应(如“提交”或类似的东西)?
  • 存储库是一个类,它公开诸如添加/编辑/删除之类的方法,并且在内部它使用您无论如何都必须拥有的 DBContext 类的实现,因此在某种程度上它充当您的包装器数据库上下文。我将在我的帖子中为您包含一个粗略的代码部分
猜你喜欢
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 2021-07-09
  • 2015-10-20
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多