【问题标题】:Store the changes done to database in Entity Framework将对数据库所做的更改存储在实体框架中
【发布时间】:2016-03-02 07:34:18
【问题描述】:

我想将对数据库所做的更改存储在一个结构或其他东西中,以便我可以在数据库上下文结束后随时引用它们。我在 C# 中使用实体框架,在 SQL Server 中使用底层数据库。

我要存储的信息是

  • 正在执行的数据库上下文
  • 表名
  • 更新列的先前值
  • 更新列的新值
  • 添加或删除的行 ID。
  • 已执行操作(更新或删除或添加)

目前我以字符串的形式存储它们。但问题是,使用这种方法我无法重现 linq 查询,因此我可以恢复更改。

在这种情况下我该如何处理。提前致谢。

【问题讨论】:

  • 您可以在SaveChanges 之前观察更改跟踪器(请参阅msdn.microsoft.com/en-us/library/…),在其后收集新添加项目的ID,并将此信息在您自己的模型中以稍后回放反转动作。
  • @Dennis 我可以在上下文 (SaveChanges) 结束后使用更改跟踪器吗?
  • SaveChanges 重置更改跟踪器状态(即丢弃旧的更改数据)。当然SaveChanges之后可以访问,但是会是“空”的。
  • 因此您可以在 SaveChanges 之前从跟踪器中复制内容,以便在 SaveChanges 之后使用。
  • @Dennis 谢谢丹尼斯。我想在保存更改后保留更改。有没有办法做到这一点,或者我可以将它们存储在其他地方吗?

标签: c# sql-server entity-framework linq


【解决方案1】:

您可以在SaveChanges 之前观察change tracker,并将更改存储在您自己的模型中。稍后,使用此模型来播放反转动作。

例如,给定这个上下文:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class SampleContext : DbContext
{
    public DbSet<Person> People { get; set; }
}

你可以写这样一个类:

public class SampleContextMemento
{
    private IEnumerable<Person> addedPeople;
    private IEnumerable<Person> deletedPeople;

    private IEnumerable<T> GetEntitiesByState<T>(SampleContext context, EntityState state)
        where T : class
    {
        return context.ChangeTracker
            .Entries<T>()
            .Where(_ => _.State == state)
            .Select(_ => _.Entity)
            .ToList();
    }

    public void RecordChanges(SampleContext context)
    {
        addedPeople = GetEntitiesByState<Person>(context, EntityState.Added);
        deletedPeople = GetEntitiesByState<Person>(context, EntityState.Deleted);
    }

    public void RollbackChanges(SampleContext context)
    {
        // delete added entities
        if (addedPeople != null)
        {
            foreach (var item in addedPeople)
            {
                context.People.Remove(context.People.Find(item.Id));
            }
        }

        if (deletedPeople != null)
        {
            // add deleted entities
            foreach (var item in deletedPeople)
            {
                context.People.Add(item);
            }
        }

        // save reverted changes
        context.SaveChanges();
    }
}

并像这样使用它:

var memento = new SampleContextMemento();

// make changes
using (var context = new SampleContext())
{
    // add some entities
    context.People.Add(new Person { Id = 100, Name = "John" });
    // remove some
    context.People.Remove(context.People.Find(1));
    // saving changes in our memento to rollback them later
    memento.RecordChanges(context);
    context.SaveChanges();
}

// rollback them
using (var context = new SampleContext())
{
    memento.RollbackChanges(context);
}

当然,通用解决方案会更复杂,但这应该会给你一个基本的概念。

【讨论】:

  • 如果我想在范围结束后做这件事怎么办。即在关闭上下文大括号之后。我怎样才能再次获得上下文。
  • @MadhurMaurya:我已经更新了答案。这适用于不同的上下文实例。
猜你喜欢
  • 2016-08-11
  • 2014-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多