我正在使用Linq to SQL,并且我想在每次更新特定记录时插入表格。
我们假设Table1
和Table2
,只要Table1
中的记录更新,我就想在Table2
中插入新记录。
目前我有工作代码,允许我在Table1
更新时更新几个字段,这是通过为UpdateTable1
函数创建部分方法来实现的,如下所示: / p>
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记录)
问题是我收到以下错误:
无法对实体执行操作,因为实际操作不是 正在改变跟踪。
任何想法如何使我的工作?
答案 0 :(得分:3)
忘记我不可靠的解决方法(如果必须,请参阅编辑历史),我找到了一种更可靠的方法来完成这项工作!
首先,忘记为此使用部分方法(例如问题中的UpdateTable1
),除非您仅修改实例记录的数据,否则这种方法效果不佳。所以我只保留这些部分方法,因为我需要更新实例中的相关字段。
执行此操作的方法是覆盖部分SubmitChanges
类中的DataContext
方法。这将允许在允许默认SubmitChanges
处理之前插入/更新/删除任何表记录(从而锁定此功能)。
在覆盖中,您可以使用DataContext
访问当前的this.GetChangeSet()
更改集,您可以循环所有更改并执行所需的任何其他表工作(例如添加日志记录)。
对于下面的示例,假设我有一个名为Table1
的标准数据库表,并且我有一个名为Table1Log
的匹配日志表,我想记录对Table1
内所做的任何更改Table1Log
,因此日志表包含与原始字段相同的所有字段,但扩展它以存储DateTime
(更改时间)和LogType
(即添加/编辑/删除)。
以下是我最终代码的重要部分:
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类型测试的替代方法可以是found here。我实际上在我的代码中使用了它并且它非常好用,我怀疑它有性能优势但是当你需要切换50多种类型时它确实有助于使事情更具可读性。
答案 1 :(得分:0)
好吧,对于插入,你真的只有两个选择。好吧,实际上是3个。
您可以向数据库添加触发器。我们将其用于我工作的变更跟踪。我们有一个更新触发器,可以插入包含更改的记录。这很有效,也很容易。
如果您想使用LINQ to SQL,您唯一的选择是按照您指定的方式插入表格,即db.Table2s.InsertOnSubmit(...)
,然后提交更改。
另一个选项,假设您的日志表与实体之间存在外键关系,则通过LINQ to SQL分配该实体关系,然后您只需插入日志实体,而无需引用数据上下文。 / p>
partial void UpdateEntity(Entity instance)
{
instance.Logs.Add(instance.createLogEntry());
}
以这种方式完成后,您不需要引用数据上下文,但根据您的情况,这可能不是一个选项。