Linq к sql, скопируйте исходный объект в новый и сохраните

У меня есть ситуация, когда я не могу только обновить исходную запись в базе данных, но вместо этого делать новую запись, скопируйте все поля со старого и примените изменения в новом. (что-то вроде этого, если переведено в код)

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.

Действительно ли возможно заставить его работать, вручную не копируя каждое поле?

25
задан secretformula 2 August 2012 в 16:43
поделиться

3 ответа

Это должно сработать:

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;
30
ответ дан 28 November 2019 в 20:49
поделиться
$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);
  }

Очевидно, что это должно быть расширено, чтобы быть менее склонным к ошибкам, но это может быть хорошим началом.

Это, безусловно, будет иметь более медленное время выполнения, чем если бы свойства были выписаны вручную, я бы предположил.

3
ответ дан 28 November 2019 в 20:49
поделиться

Вы также можете захотеть посмотреть в Plinqo. Он обладает способностью клонировать, отсоединять, прикреплять, сериализировать XML, сериализировать двоичные, многие со многими отношениями и т. Д. ... все в порядке из коробки, чтобы вам не нужно было иметь дело с этими функциями, которые должны были быть включены в первое место.

http://www.plinqo.com/

2
ответ дан 28 November 2019 в 20:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: