Самое простое решение:
Вам нужно будет отключить проверку параллелизма (UpdateCheck.Never) для всех столбцов (вы можете щелкнуть по нему в конструкторе или изменить свой шаблон, если используете шаблоны 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);
}
}
}
Лучшее решение этого типа, которое я нашел (если вы используете шаблоны T4 для LINQ to SQL, это еще проще):
Либо создайте частичный файл класса, реализующий общий интерфейс для каждого типа проверяемого объекта, либо измените шаблон таким образом, чтобы проверяемые объекты реализовали общий интерфейс, например ::
public interface IAuditable
{
string UpdatedBy { get; set; }
}
Затем измените ваши 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))
{
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);
}
}
}
}