我正在尝试存档表的实体。有几种方法可以做到这一点。其中之一是创建IsArchived列,并在删除实体或将其放入历史记录时将其设置为true。这种设计的一个缺点是使指定的表格如此重。
另一种方法是创建要记录的指定实体类的复制,制作另一个表,并在AutoMapper的帮助下将其添加到日志表中。在这种情况下,我需要大量需要存档的重复实体类。
是否存在用于归档指定实体的其他解决方案?
答案 0 :(得分:0)
您可以拥有多个具有相同架构的数据库。然后,您可以使用不同的连接字符串打开几个上下文,每个上下文对应一个数据库。查询一个,将实体附加到另一个,然后保存。
我从来没有这样做过,但它应该有效。您可能遇到麻烦,因为实体将附加到源上下文并且无法附加到目标,但是有方法可以取消附加并重新附加实体。
答案 1 :(得分:0)
我已经实施了soft delete for the purposes of undo。我的答案显示了如何克服通常与软删除相关的一些问题 - 即连接和索引。它很适合我的目的。但是,如果它被用于存档,则表格将永远增长。
您的另一个想法是创建重复的类并使用automapper。这听起来像是很多额外的编码。
我认为你可以使用相同的模式创建一个数据库 - 除了主键不会生成数据库,并且不强制执行外键。然后override the delete以便复制数据。
这样的事情:
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来覆盖删除
答案 2 :(得分:0)
最好的方法是在表中添加一个可以为空的ArchivedTimeStamp列。这样,就可以判断该行是否已存档,如果是,则存档时。
如果您担心表格大小,可以对表格进行分区,并自动将存档的行移动到辅助/较慢的物理磁盘上。您甚至可以对它进行分区,使得只有一年前存档的行必须移动到辅助分区。
有关使用分区进行SQL归档的更多信息,请访问http://www.mssqltips.com/sqlservertip/2780/archiving-sql-server-data-using-partitioning/