首先在EF代码中归档实体的最佳实践

时间:2013-10-15 19:20:44

标签: c# entity-framework ef-code-first entity-framework-5

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

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

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

3 个答案:

答案 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/