2

我正在使用 Linq to SQL,并且有一个场景,我想在更新特定记录时插入表中。

所以可以说我有Table1Table2每当Table1更新记录时,我都想将新记录插入Table2.

目前我有工作代码,允许我在更新时更新几个字段,Table1这是通过为UpdateTable1函数创建部分方法来实现的,如下所示:

partial void UpdateTable1(Table1 instance)
{
   //update some fields
   this.ExecuteDynamicUpdate(instance);
}

这很好用,而且非常有用,我想用它来确保总是在更新Table2时创建新记录Table1。顺便说一句,这主要用于记录目的。

所以这就是我接下来尝试做的事情:

partial void UpdateTable1(Table1 instance)
{
   //update some fields
   this.ExecuteDynamicUpdate(instance);
   this.ExecuteDynamicInsert(instance.ConvertToTable2());
}

(我这里使用的是扩展方法,基于Table1实例创建了Table2记录)

问题是我收到以下错误:

无法对实体执行该操作,因为它没有被跟踪更改。

有什么想法可以让我完成这项工作吗?

4

2 回答 2

3

忘记我不可靠的解决方法(如果必须,请参阅编辑历史记录),我找到了一种更可靠的方法来完成这项工作!

首先,忘记为此使用部分方法(例如UpdateTable1在问题中),除非您仅修改实例记录的数据,否则它效果不佳。所以我保留这些部分方法只是为了我需要更新实例中的相关字段。

这样做的SubmitChanges方法是覆盖部分DataContext类中的方法。这将允许在您允许处理默认值之前插入/更新/删除任何表记录SubmitChanges(并因此锁定此功能)。

在覆盖内,您可以使用 访问当前DataContext更改集this.GetChangeSet(),从中可以循环所有更改并执行所需的任何其他表工作(例如添加日志记录)。

对于下面的示例,假设我有一个名为的标准数据库表,并且我Table1有一个名为a (更改时间)和 a (即添加/编辑/删除)。Table1LogTable1Table1LogDateTimeLogType

这是我最终代码的重要部分:

partial class MyDataContext
{

    public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
    {

        var set = this.GetChangeSet();//get a list of all pending changes

        foreach (var item in set.Inserts)
        {
            AddLog(item, LogType.Add);
        }
        foreach (var item in set.Updates)
        {
            AddLog(item, LogType.Edit);
        }
        foreach (var item in set.Deletes)
        {
            AddLog(item, LogType.Delete);
        }

        base.SubmitChanges(failureMode);//allow the DataContext to perform it's default work (including your new log changes)

    }

    public void AddLog(object item, LogType logType)
    {

        //some painful type testing, so feel free to refactor this as you wish
        if(item is Table1)
        {
           var log = (item as Table1).ToLog(logType);//ToLog() is an extension method (one for each type)
           this.Table1_Logs.InsertOnSubmit(log);//add the log record ready to be submitted
        }
        else if(item is Table2)
        {
           //same again
        }
        //...repeat for each table class type

    }

}

注意:可以在此处找到if/else 类型测试的替代方法。我实际上在我的代码中使用了它,它工作得非常好,我怀疑它是否有性能优势,但是当你需要切换 50 多种类型时,它确实有助于使事情更具可读性。

于 2012-08-13T15:04:00.340 回答
0

好吧,对于插入,您实际上只有两个选择。好吧,实际上是3。

您可以将触发器添加到数据库。我们用它来跟踪我工作的地方。我们有一个更新触发器,它插入带有更改的记录。它很有效,也很容易。

如果您想使用 LINQ to SQL,您唯一的选择是插入您指定的表,即db.Table2s.InsertOnSubmit(...),然后提交更改。

另一种选择,假设您的日志表和实体之间有外键关系,是通过 LINQ to SQL 分配该实体关系,然后您可以简单地插入您的日志实体,而无需引用数据上下文。

partial void UpdateEntity(Entity instance)
{
    instance.Logs.Add(instance.createLogEntry());
}

以这种方式完成后,您将不需要对数据上下文的引用,但是根据您的情况,这可能不是一个选项。

于 2012-08-13T15:20:54.433 回答