Подтвердить что ты не робот

Данные клонирования для платформы Entity Framework

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

Теперь мне нужно сделать операции копирования/клонирования с Entity Framework. Сначала я начал писать так:

foreach(sourcedata1 in table1)
{
   ... create new table
   ... copy data
   ... create Guid
   ... add
   foreach(sourcedata2 in table2)
   {
       ... create new table
       ... copy data
       ... create Guid
       ... add       

       ... and so on
   }
}

Проблема в том, что это не очень хороший способ сделать это. Есть ли какая-либо информация о клонированном виде (кроме Guid, которая должна быть сгенерирована для новых строк) или мне нужно вручную копировать все?

Другое решение

Вы также можете использовать EmitMapper или AutoMapper для копирования свойств.

4b9b3361

Ответ 2

Чтобы клонировать Entity в Entity Framework, вы могли бы просто отсоединить объект от DataContext, а затем снова добавить его в EntityCollection.

context.Detach(entity);
entityCollection.Add(entity);

Обновить для EF6 + (из комментариев)

context.Entry(entity).State = EntityState.Detached;
entity.id = 0;
entity.property = value;
context.Entry(entity).State = EntityState.Added;
context.SaveChanges();

Ответ 3

public static EntityObject Clone(this EntityObject Entity)
{
    var Type = Entity.GetType();
    var Clone = Activator.CreateInstance(Type);

    foreach (var Property in Type.GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.SetProperty))
    {
        if (Property.PropertyType.IsGenericType && Property.PropertyType.GetGenericTypeDefinition() == typeof(EntityReference<>)) continue;
        if (Property.PropertyType.IsGenericType && Property.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>)) continue;
        if (Property.PropertyType.IsSubclassOf(typeof(EntityObject)))  continue;

        if (Property.CanWrite)
        {
            Property.SetValue(Clone, Property.GetValue(Entity, null), null);
        }
    }

    return (EntityObject)Clone;
}

Это простой метод, который я написал. Он должен работать для большинства людей.

Ответ 4

Чтобы добавить новую строку, содержимое которой основано на существующей строке, выполните следующие действия:

  • Получить объект на основе начальной строки.
  • Задайте состояние записи для добавления объекта.
  • Изменить сущность.
  • Сохранить изменения.

Вот пример:

var rabbit = db.Rabbits.First(r => r.Name == "Hopper");
db.Entry(rabbit).State = EntityState.Added;
rabbit.IsFlop = false;
db.SaveChanges();

Ответ 5

Если вы хотите создать копию объекта для сравнения позже в вашем исполнении кода, вы можете выбрать объект в новом контексте db.

Если, например, вы обновляете объект, то позже в коде вы хотите сравнить обновленный и оригинальный объект:

var db = new dbEntityContext();
var dbOrig = new dbEntityContext();

var myEntity = db.tblData.FirstOrDefault(t => t.Id == 123);
var myEntityOrig = dbOrig.tblData.FirstOrDefault(t => t.Id == 123);

//Update the entity with changes
myEntity.FirstName = "Gary";

//Save Changes
db.SaveChnages();

В этот момент myEntity.FirstName будет содержать "Gary", тогда как myEntityOrig.FirstName будет содержать исходное значение. Полезно, если у вас есть функция для регистрации изменений, где вы можете пройти в обновленном и оригинальном объекте.

Ответ 6

Очень короткий способ дублирования объектов с использованием дженериков (VB, извините).
Он копирует значения внешнего ключа (внешние идентификаторы), но не загружает связанные объекты.

<Extension> _
Public Function DuplicateEntity(Of T As {New, Class})(ctx As myContext, ent As T) As T
    Dim other As New T 'T is a proxy type, but New T creates a non proxy instance
    ctx.Entry(other).State = EntityState.Added 'attaches it to ctx
    ctx.Entry(other).CurrentValues.SetValues(ent) 'copies primitive properties
    Return other
End Function

Например:

newDad = ctx.DuplicateEntity(oDad)
newDad.RIDGrandpa ' int value copied
newDad.Grandpa    ' object for RIDGrandpa above, equals Nothing(null)
newDad.Children   ' nothing, empty

Я точно не знаю, как перезагрузить Grandpa в этом случае.
Это не работает:

ctx.SaveChanges()
ctx.Entry(newDad).Reload()

но на самом деле, никаких проблем. Я бы предпочел назначить Grandpa вручную, если мне это нужно.

newDad.Grandpa = oDad.Grandpa

EDIT: Как MattW предлагает в своем комментарии, отделяя и обнаруживая новый объект, вы загружаете его дочерние (а не коллекции).

ctx.Entry(newDad).State = EntityState.Detached
ctx.Find(newDad.RowId) 'you have to know the key name