如何使用 LINQ to SQL 还原关联记录
How to Revert Associated Records using LINQ to SQL
我有一个注册系统的数据库,其中有两个 table,Person
和 Class
,它们具有多对多关系。在它们之间,有一个名为 Enrollment
的连接 table。下面的代码显示了前面提到的 Person
和 Enrollment
类:
[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的记录肯定没有提交到数据库。
我有一个注册系统的数据库,其中有两个 table,Person
和 Class
,它们具有多对多关系。在它们之间,有一个名为 Enrollment
的连接 table。下面的代码显示了前面提到的 Person
和 Enrollment
类:
[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的记录肯定没有提交到数据库。