我正在尝试归档表的实体。有几种方法可以做到这一点。其中之一是创建 IsArchived 列,并在实体被删除或放入历史记录时将其设置为 true。这种设计的缺点之一会使指定的桌子如此沉重。
另一种方法是创建要记录的指定实体类的副本,创建另一个表,并在 AutoMapper 的帮助下将其添加到日志表中。在这种情况下,我需要大量需要存档的重复实体类。
是否有其他用于归档指定实体的解决方案?
我正在尝试归档表的实体。有几种方法可以做到这一点。其中之一是创建 IsArchived 列,并在实体被删除或放入历史记录时将其设置为 true。这种设计的缺点之一会使指定的桌子如此沉重。
另一种方法是创建要记录的指定实体类的副本,创建另一个表,并在 AutoMapper 的帮助下将其添加到日志表中。在这种情况下,我需要大量需要存档的重复实体类。
是否有其他用于归档指定实体的解决方案?
最好的方法是向表中添加一个可为空的 ArchivedTimeStamp 列。通过这种方式,可以判断该行是否已归档,如果是,则可以判断它是何时归档的。
如果您担心表大小,可以对表进行分区并自动将归档行移动到辅助/较慢的物理磁盘上。您甚至可以对它进行分区,即只有一年前存档的行必须移动到辅助分区。
有关使用分区进行 SQL 归档的更多信息,请访问 http://www.mssqltips.com/sqlservertip/2780/archiving-sql-server-data-using-partitioning/
为了 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 来覆盖删除
您可以拥有多个具有相同架构的数据库。然后,您可以使用不同的连接字符串打开几个上下文,每个数据库一个。查询一个,将实体附加到另一个,然后保存。
我从来没有这样做过,但它应该工作。您可能会遇到麻烦,因为实体将附加到源上下文并且无法附加到目标,但是有一些方法可以取消附加和重新附加实体。