У меня есть ситуация, когда я не могу только обновить исходную запись в базе данных, но вместо этого делать новую запись, скопируйте все поля со старого и примените изменения в новом. (что-то вроде этого, если переведено в код)
var original = from _orig in context.Test where _orig.id == 5 select _orig;
Test newTest = new Test();
newTest = original;
newTest.id = 0;
context.Test.InsertOnSubmit(newTest);
context.SubmitChanges();
original.parent_id = newTest.id;
original.isActive = 0;
который дает следующее исключение:
Cannot add an entity that already exists.
Действительно ли возможно заставить его работать, вручную не копируя каждое поле?
Это должно сработать:
Generic Clone() Method
Этот метод создаст полный клон любого объекта путем его сериализации. Оригинальная идея пришла как из here, так и из here.
/// <summary>
/// Clones any object and returns the new cloned object.
/// </summary>
/// <typeparam name="T">The type of object.</typeparam>
/// <param name="source">The original object.</param>
/// <returns>The clone of the object.</returns>
public static T Clone<T>(this T source) {
var dcs = new DataContractSerializer(typeof(T));
using(var ms = new System.IO.MemoryStream()) {
dcs.WriteObject(ms, source);
ms.Seek(0, System.IO.SeekOrigin.Begin);
return (T)dcs.ReadObject(ms);
}
}
Ваш пример кода
Теперь с помощью вышеуказанного метода расширения, ваш код должен работать, если немного подкорректировать:
var original = from _orig in context.Test where _orig.id == 5 select _orig;
Test newTest = original.Clone();
newTest.id = 0;
context.Test.InsertOnSubmit(newTest);
context.SubmitChanges();
original.parent_id = newTest.id;
original.isActive = 0;
$svr_os=strtolower(reset(explode(' ',php_uname('s'))));
$isLinux=$svr_os==='linux';
$isWindows=$svr_os==='windows';
-121--3205631- Ручное срабатывание System.gc не является хорошим ответом, как опубликовали здесь другие. Это не гарантировано, и это запускает полный gc, который, вероятно, повесит ваш сервер на долгое время, пока он работает (> 1 сек, если вы даете вашему серверу ГБ оперативной памяти, я видел несколько минут пауз на больших системах). Вы можете настроить свой gc, который, безусловно, поможет, но не полностью исправить проблему.
Если вы читаете объекты из одного потока, а затем записываете их в другой, то есть точка, в которой вы держите весь объект в памяти. Если эти объекты, как вы заявляете, велики, то это может быть вашей проблемой. Попробуйте переписать ввод-вывод так, чтобы считывать байты из 1 потока и записывать их в другой без явного удержания всего объекта (хотя я не вижу, как это будет работать с сериализацией/десериализацией объектов, если нужно проверить/проверить объекты).
-121--2623968-Вы можете использовать отражение для итерации над свойствами и установки их
foreach (var prop in original.GetType().GetProperties())
{
prop.SetValue(newTest, prop.GetValue(original,null), null);
}
Очевидно, что это должно быть расширено, чтобы быть менее склонным к ошибкам, но это может быть хорошим началом.
Это, безусловно, будет иметь более медленное время выполнения, чем если бы свойства были выписаны вручную, я бы предположил.
Вы также можете захотеть посмотреть в Plinqo. Он обладает способностью клонировать, отсоединять, прикреплять, сериализировать XML, сериализировать двоичные, многие со многими отношениями и т. Д. ... все в порядке из коробки, чтобы вам не нужно было иметь дело с этими функциями, которые должны были быть включены в первое место.