最简单的解决方案:
您必须对所有列禁用并发检查(UpdateCheck.Never)(您可以在设计器中按住shift键单击它,或者在使用T4模板时修改模板)。或者,您必须复制下面示例中的每个字段(可以生成模板方法来执行此操作)。
无论如何:
MyDataContext db = new MyDataContext();
MyDataContext db2 = new MyDataContext();
Car betsy = db.Cars.First(c => c.Name == "Betsy");
Car betsy2 = new Car();
betsy2.Id= betsy.Id;
db2.Cars.Attach(betsy2);
/* Could be GetName() or whatever, but allows same */
betsy2.UpdatedBy = betsy.UpdatedBy;
betsy2.OtherField = "TestTestTest";
db2.SubmitChanges();
下面还有一些其他的“解决方案”。不幸的是,所有这些都涉及到一个双重更新/随便什么,如果你正在执行一个删除操作,就不会真正起作用。当您在审计时,可能正在备份到另一个表中,在您得到第二个非“|”或其他东西(如果它总是在事务中,可能不是世界末日)时,您可能希望在触发器中用“|”来更新最后一个审计条目。不过,这一切都不理想。
混乱的解决方案:
MyDataContext db = new MyDataContext();
Car car = db.Cars.First(c => c.Id == 1);
car.Name = "Betsy";
car.UpdatedBy = String.Format("{0}|{1}", car.UpdatedBy, DateTime.Ticks);
db.SubmitChanges();
car.UpdatedBy = car.UpdatedBy.Substring(0, car.UpdatedBy.LastIndexOf('|'));
db.SubmitChanges();
稍微好一点的解决方案是:
public partial class MyDataContext : DataContext
{
public override void SubmitChanges(ConflictMode failureMode)
{
ChangeSet cs = base.GetChangeSet();
foreach (object e in cs.Updates.Union(cs.Inserts))
{
PropertyInfo updatedBy = e.GetType()
.GetProperties()
.FirstOrDefault(p => p.Name == "UpdatedBy");
if (updatedBy == null)
{
base.SubmitChanges(failureMode);
return;
}
string updatedByValue = updatedBy.GetValue(e, null);
string tempValue = String.Format("{0}|{1}", updatedByValue, DateTime.Ticks;
updatedBy.SetValue(e, tempValue);
base.SubmitChanges(failureMode);
updatedBy.SetValue(e, tempValue.Substring(0, tempValue.LastIndexOf('|')));
base.SubmitChanges(failureMode);
}
}
}
我找到了这种类型的最佳解决方案(如果您使用的是用于LINQ to SQL的T4模板,这就更简单了):
为每个被审计实体类型创建一个实现公共接口的部分类文件,或者修改模板,以便被审计实体实现公共接口,例如:
public interface IAuditable
{
string UpdatedBy { get; set; }
}
然后按如下方式修改您的提交更改:
public partial class MyDataContext : DataContext
{
public override void SubmitChanges(ConflictMode failureMode)
{
ChangeSet cs = base.GetChangeSet();
foreach (object e in cs.Updates.Union(cs.Inserts))
{
if (typeof(IAuditable).IsAssignableFrom(e))
{
string tempValue = String.Format("{0}|{1}", ((IAuditable)e).UpdatedBy, DateTime.Ticks);
((IAuditable)e).UpdatedBy = tempValue;
base.SubmitChanges(failureMode);
((IAuditable)e).UpdatedBy = tempValue.Substring(0, tempValue.LastIndexOf('|'));
base.SubmitChanges(failureMode);
}
}
}
}