0

我正在尝试归档表的实体。有几种方法可以做到这一点。其中之一是创建 IsArchived 列,并在实体被删除或放入历史记录时将其设置为 true。这种设计的缺点之一会使指定的桌子如此沉重。

另一种方法是创建要记录的指定实体类的副本,创建另一个表,并在 AutoMapper 的帮助下将其添加到日志表中。在这种情况下,我需要大量需要存档的重复实体类。

是否有其他用于归档指定实体的解决方案?

4

3 回答 3

1

最好的方法是向表中添加一个可为空的 ArchivedTimeStamp 列。通过这种方式,可以判断该行是否已归档,如果是,则可以判断它是何时归档的。

如果您担心表大小,可以对表进行分区并自动将归档行移动到辅助/较慢的物理磁盘上。您甚至可以对它进行分区,即只有一年前存档的行必须移动到辅助分区。

有关使用分区进行 SQL 归档的更多信息,请访问 http://www.mssqltips.com/sqlservertip/2780/archiving-sql-server-data-using-partitioning/

于 2013-10-17T04:23:53.433 回答
0

为了 undo 的目的,我实现了软删除。我的回答显示了如何克服通常与软删除相关的一些问题——即连接和索引。它非常适合我的目的。但是,如果它用于归档,那么这些表将永远增长。

您的另一个想法是创建重复的类并使用 automapper。这听起来像很多额外的编码。

我认为您可以创建具有相同架构的数据库 - 除非主键不会由数据库生成,并且外键不会被强制执行。然后覆盖删除,以便复制数据。

像这样的东西:

public override int SaveChanges()
{
   foreach (var entry in ChangeTracker.Entries()
             .Where(p => p.State == EntityState.Deleted 
             && p.Entity is ModelBase))//I have a base class for entities with a single 
                                       //"ID" property - all my entities derive from this
    CustomDelete(entry);

    return base.SaveChanges();
}

private void CustomDelete(DbEntityEntry entry)
{
    var e = entry.Entity as ModelBase;
    string tableName = GetTableName(e.GetType());
    string sql = String.Format(@"INSERT INTO archive.{0} SELECT * FROM {0} WHERE ID = @id; 
                                 DELETE FROM {0} WHERE ID = @id", tableName);
    Database.ExecuteSqlCommand(
             sql
             , new SqlParameter("id", e.ID));
    entry.State = EntityState.Detached;
}

请注意,在 EF6 中,您还可以通过在使用映射到存储过程时更改迁移文件中的 sql 来覆盖删除

于 2013-10-16T08:47:34.590 回答
0

您可以拥有多个具有相同架构的数据库。然后,您可以使用不同的连接字符串打开几个上下文,每个数据库一个。查询一个,将实体附加到另一个,然后保存。

我从来没有这样做过,但它应该工作。您可能会遇到麻烦,因为实体将附加到源上下文并且无法附加到目标,但是有一些方法可以取消附加和重新附加实体。

于 2013-10-15T20:31:48.117 回答