如何使用 LINQ to SQL 还原关联记录

How to Revert Associated Records using LINQ to SQL

我有一个注册系统的数据库,其中有两个 table,PersonClass,它们具有多对多关系。在它们之间,有一个名为 Enrollment 的连接 table。下面的代码显示了前面提到的 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 恢复关联记录的方法吗?

您必须在您的 dataContext 中刷新注册记录 table,如下所示。代码中需要添加两行。我已经在评论中标记出来供大家参考了。

   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 table 的记录。

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

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

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

    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的记录肯定没有提交到数据库。