Я использую Entity Framework 5 (DBContext
), и я пытаюсь найти лучший способ глубоко скопировать объект (то есть скопировать объект и все связанные объекты), а затем сохранить новые объекты в базе данных. Как я могу это сделать? Я изучил методы расширения, такие как CloneHelper
, но я не уверен, применим ли он к DBContext
.Entity Framework 5 глубокая копия/клонирование объекта
ответ
Один дешевые простой способ клонировать объект должны сделать что-то вроде этого:
var originalEntity = Context.MySet.AsNoTracking()
.FirstOrDefault(e => e.Id == 1);
Context.MySet.Add(originalEntity);
Context.SaveChanges();
трюка здесь является AsNoTracking() - при загрузке объекта, как это, ваш контекст не знает о он и когда вы вызываете SaveChanges, он будет рассматривать его как новый объект.
Если MySet
имеет ссылку на MyProperty
и вы хотите копию этого тоже, просто использовать Include
:
var originalEntity = Context.MySet.Include("MyProperty")
.AsNoTracking()
.FirstOrDefault(e => e.Id == 1);
Этот трюк просто защитил меня довольно долго :-). Но с моей конфигурацией DbContext было исключение из-за невозможности автоматического добавления Entity. Мне пришлось пройти через ObjectContext, как этот 'DirectCast (DbContext, IObjectContextAdapter) .ObjectContext.AddObject (entitySetName, entity)' – Patrick
У меня есть проекция из ef-контекста, подобная этому 'dbContext, Select (x => {a = x, ab = x.MyCollection.Where (g => g.Id> 2)}) ToList() 'Если я добавляю' AsNoTracking() 'Потеря данных из запроса. – Eldho
Это отлично поработало для меня с использованием EF Core. Однако мне пришлось установить первичные ключи родителя и вложенные объекты в Guid.Empty, чтобы предотвратить попытку EF вставить повторяющиеся строки в базу данных. Если вы используете целые ключи, я подозреваю, что их установка в 0 будет иметь тот же эффект. – agileMike
Вот еще один вариант.
Я предпочитаю его в некоторых случаях, потому что он не требует, чтобы вы выполняли запрос специально, чтобы клонировать данные. Вы можете использовать этот метод для создания клонов сущностей, которые вы уже получили из базы данных.
//Get entity to be cloned
var source = Context.ExampleRows.FirstOrDefault();
//Create and add clone object to context before setting its values
var clone = new ExampleRow();
Context.ExampleRows.Add(clone);
//Copy values from source to clone
var sourceValues = Context.Entry(source).CurrentValues;
Context.Entry(clone).CurrentValues.SetValues(sourceValues);
//Change values of the copied entity
clone.ExampleProperty = "New Value";
//Insert clone with changes into database
Context.SaveChanges();
Этот метод копирует текущие значения из источника в новую добавленную строку.
Это отлично работает, если вы хотите, чтобы клон был вставлен вместе с обновлениями оригинала в одном SaveChanges – Dacker
'SetValues' не работает, если новый объект не подключен к контекст. Он генерирует исключение InvalidOperationException. Если все, что вы хотите сделать, - клонировать объект в отдельном состоянии, вы можете добавить объект в контекст, установить его текущие значения, а затем отсоединить. – Suncat2000
Это универсальный метод расширения, который позволяет использовать общее клонирование.
Вы должны получить System.Linq.Dynamic
от nuget.
public TEntity Clone<TEntity>(this DbContext context, TEntity entity) where TEntity : class
{
var keyName = GetKeyName<TEntity>();
var keyValue = context.Entry(entity).Property(keyName).CurrentValue;
var keyType = typeof(TEntity).GetProperty(keyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).PropertyType;
var dbSet = context.Set<TEntity>();
var newEntity = dbSet
.Where(keyName + " = @0", keyValue)
.AsNoTracking()
.Single();
context.Entry(newEntity).Property(keyName).CurrentValue = keyType.GetDefault();
context.Add(newEntity);
return newEntity;
}
Единственное, что вам нужно реализовать, это метод GetKeyName. Это может быть что угодно: от до return the first guid property
или вернуть первое имущество, помеченное DatabaseGenerated(DatabaseGeneratedOption.Identity)]
.
В моем случае я уже отмечал свои классы с [DataServiceKeyAttribute("EntityId")]
private string GetKeyName<TEntity>() where TEntity : class
{
return ((DataServiceKeyAttribute)typeof(TEntity)
.GetCustomAttributes(typeof(DataServiceKeyAttribute), true).First())
.KeyNames.Single();
}
- 1. Entity Framework 6 глубокая копия/клонирование объекта с динамической глубиной
- 2. двухуровневая глубокая основная информация для Entity Framework
- 3. Entity Framework 5 Таблица Связь
- 4. Свойства объекта Entity Framework
- 5. Entity Framework 5, несколько моделей, Same Entity
- 6. Entity Framework 5 Lambda Запросы
- 7. CreateQuery using Entity Framework 5
- 8. Entity Framework 5 без транзакций
- 9. Entity Framework 5 Complex Types
- 10. Entity Framework 5 рекурсивные отношения
- 11. Entity Framework 5 Отсутствующие ассоциации
- 12. Entity Framework 5 функции импорта
- 13. Entity Framework 5 Soft Удалить
- 14. Entity Framework 5 Обновление записи
- 15. Entity Framework 5 Сложные типы
- 16. Entity Framework 5 Enum Naming
- 17. Entity Framework 5 кэширование вопрос
- 18. Результаты хранимой процедуры карты для объекта в Entity Framework 5
- 19. Entity Framework 5 - Миграции и создание таблицы из объекта
- 20. Entity Framework 5: создать тип объекта для таблицы объединения
- 21. Использование Entity Framework 5 для возврата объекта, эквивалентного datareader
- 22. Мысли о Entity Framework 5 и многопоточности
- 23. Сохранение большого графа с Entity Framework 5
- 24. Entity Framework: загрузка связанного объекта
- 25. Entity Framework, Получение части объекта
- 26. Entity-Framework загружает часть объекта?
- 27. Entity Framework: создание автономного объекта
- 28. Entity framework - Недопустимое имя объекта
- 29. Entity Framework - фильтр дочернего объекта
- 30. Длина объекта структуры Entity Framework
Я попытался Deep клона/дублировать объекты сущностей, используя отражение, описанное в следующей [ссылка] (http://code.msdn.microsoft. com/CSEFDeepCloneObject-12a5cb95), но, как я понимаю, производные типы EntityObject не поддерживаются API-интерфейсом DbContext. – kypk