Linq-to-SQL中更新记录及其关联关系的一般最佳实践

3
我有一个关于在Linq-to-SQL中更新记录的一般性问题。假设在我的数据模型中,我有一个基本记录(表 - Person),与一组类别(表 - Category)的m:m关系。因此,我有一个联合表(PersonCategory),它具有对PersonID和CategoryID的外键。
当我想要更新Person时,我可能有新的PersonCategory记录要添加,也可能想要删除其他PersonCategory记录。如何处理这样的情况是最佳实践?我是否需要删除Person.RelatedPersonCategories中的所有记录,然后再添加新的记录?LINQ-to-SQL是否足够聪明,可以协商实际添加、编辑或删除PersonCategory表中的记录(根据其外键)?
感谢任何帮助!
2个回答

3
只要有一个活动的DataContext类实例来跟踪更改,LINQ to SQL就会愉快地在关联表中插入/更新/删除行,每当模型中映射关系的集合中的对象被修改并调用DataContext.SubmitChanges()方法时。
例如:
using (var db = new DataContext())
{
    var person = db.Persons.Where(p => p.Name == "Foo").SingleOrDefault();

    if (person != null)
    {
        // Inserts a new row in the 'PersonCategory' table
        // associated to the current 'Person'
        // and to the 'Category' with name 'Employee'
        person.PersonCategories.Add(new PersonCategory() { CategoryName = "Employee" });

        // Updates the 'CategoryName' column in the first row
        // of the 'PersonCategory' table associated to the current 'Person'
        person.PersonCategories(0).CategoryName = "Consultant";

        db.SubmitChanges();
    }
}

如果您在“断开连接”模式下更改模型对象,即使用最初创建这些对象的DataContext实例不再存在,则情况会有所不同。
在这种情况下,当具有修改后集合的对象附加到新的DataContext并使用Table(TEntity).Attach方法,然后使用DataContext.SubmitChanges()时,关联表上的插入/删除操作将正常工作。
但是,对集合中任何现有对象的修改将不会自动应用于关联表。为了做到这一点,必须针对集合中的每个对象手动调用Table(TEntity).Attach方法。
以下是来自MSDN文档的引用:
当一个新实体被附加时,任何子集合的延迟加载器(例如来自相关表的实体集合的EntitySet集合)都会被初始化。当调用SubmitChanges时,子集合的成员将被置于未修改状态。要更新子集合的成员,必须显式调用Attach并指定该实体。
以下是一个具体的示例:
// The 'Person' object has been detached
// from the originating 'DataContext', which is now disposed
person.PersonCategories.Add(new PersonCategory() { CategoryName = "Employee" });
person.PersonCategories(0).CategoryName = "Consultant";

using (var db = new DataContext())
{
    // Will detect added and deleted objects
    // in the 'PersonCategory' collection        
    db.Person.Attach(person);

    // Required to detect and modifications
    // to existing objects in the 'PersonCategory' collection
    foreach (var personCategory in person.PersonCategories)
    {
        db.PersonCategory.Attach(personCategory);
    }

    db.SubmitChanges();
}

0

根据我的经验,您在这里不需要做任何特殊的事情。 PersonCategory 只是一个实体,您可以像处理其他实体一样通过 InsertOnSubmit()DeleteOnSubmit() 在数据上下文中添加或删除相关表实例的实例。对现有的 PersonCategory 对象的更新由更改跟踪系统处理。

您当然不需要先删除所有项目,然后再将其全部添加回来。

当您查看模型代码时,它会变得更加复杂 - 假设您在数据库中正确设置了外键,生成的模型代码应该完全处理关联管理。

例如,

  • Person 将具有一个 EntitySet<PersonCategory>

  • PersonCategory 将具有一个 EntityRef<Person>EntityRef<Category>

  • Category 将具有一个 EntitySet<PersonCategory>

每当对这些字段进行更改时,相关对象也会被更新:

  • 如果我将PersonCategory上的Person属性更改为null,则代码还将通过从先前的人的EntitySet<PersonCategory>中删除该PersonCategory来相应地更新相关的EntitySet<PersonCategory>

  • 如果我向一个人的EntitySet<PersonCategory>中添加一个新的PersonCategory,则代码将自动将Person属性设置为新的父级Person

所以,基本答案是LINQ to SQL足够聪明,可以为您处理这个问题 - 只要您从数据库生成模型代码即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接