【问题标题】:How to Revert Associated Records using LINQ to SQL如何使用 LINQ to SQL 还原关联记录
【发布时间】:2016-06-18 05:58:44
【问题描述】:

我有一个用于注册系统的数据库,其中有两个表,PersonClass,它们具有多对多关系。在它们之间,有一个名为Enrollment 的连接表。以下代码显示了上述PersonEnrollment 类:

[Table]
public class Person
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int Id { get; set; }

    [Column()]
    public string FirstName;

    [Column()]
    public string LastName;

    private EntitySet<Enrollment> _enrollment = new EntitySet<Enrollment>();

    [System.Data.Linq.Mapping.Association(Name = "FK_Enrollment_Person", Storage = "_enrollment", OtherKey = "StudentId", ThisKey = "Id")]
    public IList<Enrollment> Enrollment
    {
        get { return _enrollment; }
        set { _enrollment.Assign(value); }
    }
}

[Table]
public class Enrollment
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int Id { get; set; }

    [Column()]
    public int StudentId;

    [Column()]
    public int ClassId;

    [Column()]
    public DateTime EnrollDate;

}

还有一个DataContext的子类来表示数据库:

[Database]
public class Database : DataContext
{
    public Database()
        : base(ConfigurationManager.ConnectionStrings["AppConnection"].ConnectionString)
    {
    }
}

所以我可以检索Person的记录及其关联的Enrollment记录如下:

    Database db = new Database();
    var people = db.GetTable<Person>();

我需要的是有一种方法可以在修改后将这些记录恢复为原始状态。我尝试了DataContext.Refresh 方法,它确实适用于Person,但不适用于Enrollment 的相关记录。

在以下示例中,我修改了Enrollment 记录的EnrollDate 属性,但在我调用DataContext.Refresh 后它们不会回滚。

        Database db = new Database();
        var people = db.GetTable<Person>();

        var enrolledPeople = people.Where(o => o.Enrollment.Count > 0);
        foreach(var person in enrolledPeople)
        {
            Console.WriteLine("Original Enroll Date:");
            foreach (var enrollment in person.Enrollment)
            {
                Console.WriteLine(enrollment.EnrollDate);
                enrollment.EnrollDate = DateTime.Now;
            }

            person.Enrollment.Add(new Enrollment() );

            db.Refresh(RefreshMode.OverwriteCurrentValues, person);

            Console.WriteLine("Enroll Date After being refreshed:");
            foreach (var enrollment in person.Enrollment)
            {
                Console.WriteLine(enrollment.EnrollDate);
            }                
        } 

有人知道使用 LINQ to SQL 恢复关联记录的方法吗?

【问题讨论】:

  • 我可以看到您总共做了两个更改。 1. 您添加了一个新的注册 2. 更改了所有现有注册的注册日期。我相信您与一个人关联的注册的enrollDate 属性不会令人耳目一新。但是新增的招生呢?刷新后,在使用 foreach 进行迭代时,您是否还会在集合中看到新的注册对象?
  • 这只是 Refresh 方法不起作用的两个示例,因此它们只是在修改后保持不变,就好像该方法没有被调用一样。
  • 我在 sql profiler 中检查了刷新方法正在发送查询以仅获取人员数据,但是当我们重申其注册属性时,即使您重复 GetTable API 调用,它也会使用缓存副本.
  • 在这种情况下,即使清除缓存似乎也没有任何帮助。 stackoverflow.com/questions/2141208/…
  • 感谢您提供的重要信息,我已经根据您的建议找到了解决问题的方法。

标签: c# linq-to-sql


【解决方案1】:

您必须刷新 dataContext 中的 Enrollment 表的记录,如下所示。代码中有两行需要添加。我已在评论中标记它们以供您参考。

   Database db = new Database();
    var people = db.GetTable<Person>();
    //Modified line # 1
    var enrollments = db.GetTable<Enrollment>();


    var enrolledPeople = people.Where(o => o.Enrollment.Count > 0);
    foreach(var person in enrolledPeople)
    {
        Console.WriteLine("Original Enroll Date:");
        foreach (var enrollment in person.Enrollment)
        {
            Console.WriteLine(enrollment.EnrollDate);
            enrollment.EnrollDate = DateTime.Now;
        }

        person.Enrollment.Add(new Enrollment() );

        db.Refresh(RefreshMode.OverwriteCurrentValues, person);
        //Modified line # 2
        db.Refresh(RefreshMode.OverwriteCurrentValues, enrollments);

        Console.WriteLine("Enroll Date After being refreshed:");
        foreach (var enrollment in person.Enrollment)
        {
            Console.WriteLine(enrollment.EnrollDate);
        }                
    } 

注意:唯一需要注意的是,它不会丢弃您添加到注册中的新记录。它只会用数据库中已经存在的行的最新值刷新Enrollment 表的记录。

【讨论】:

  • 是的,它确实有效。我可以通过检查它的 ID 来丢弃新记录,所以这不是问题 :)
【解决方案2】:

根据RBT的回答,我还加了一段代码来丢弃新增的记录:

    Database db = new Database();
    var people = db.GetTable<Person>();
    var enrollments = db.GetTable<Enrollment>();

    var enrolledPeople = people.Where(o => o.Enrollment.Count > 0);
    foreach(var person in enrolledPeople)
    {
        Console.WriteLine("Original Enroll Date:");
        foreach (var enrollment in person.Enrollment)
        {
            Console.WriteLine(enrollment.EnrollDate);
            enrollment.EnrollDate = DateTime.Now;
        }

        person.Enrollment.Add(new Enrollment() );

// beginning of rollback
        db.Refresh(RefreshMode.OverwriteCurrentValues, person);
        db.Refresh(RefreshMode.OverwriteCurrentValues, enrollments);

        for (int i= person.Enrollment.Count-1; i>=0; i--)
        {
            if (person.Enrollment[i].Id == 0)
                person.Enrollment.RemoveAt(i);
        }
// end of rollback   

        Console.WriteLine("Enroll Date After being refreshed:");
        foreach (var enrollment in person.Enrollment)
        {
            Console.WriteLine(enrollment.EnrollDate);
        }                
    }    

因为在我的例子中 ID 总是从 1 开始,所以 ID 为 0 的记录一定没有提交到数据库。

【讨论】:

  • 艾萨克辛苦了!
【解决方案3】:

您需要刷新注册对象。注册不“拥有”一个人。他们不是其中的一部分。它们是独立的实体。刷新适用于您传入的一个实体。

想象一下刷新刷新了整个对象图。数据库往往是循环连接的。单个 Refresh 调用最终可能会影响 所有对象,并根据加载和映射的内容随机更改其行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多