Entity Framework - вставьте запись одного класса в другой «идентичный» объект - PullRequest
0 голосов
/ 24 сентября 2019

Использование базы данных первой сущности.Вставка записей в одну из моих таблиц, никаких проблем.Затем я обнаружил при определенных, очень редких обстоятельствах, что я получаю дубликаты записей, которые на самом деле в порядке.Поэтому я планировал разобраться с ними: создать идентичную таблицу, перехватить исключение, поместить дубликат в идентичную таблицу и изучить его на более позднем этапе.

Однако я наивно полагал, что это идентичные таблицы,Я мог бы просто вставить объект, который я уже создал, в другую таблицу «ошибок», что, очевидно, я не могу сделать («не могу преобразовать из« original_class »в« new_class »»), что я понимаю.

Так есть ли лучший способ сделать то, что я пытаюсь достичь, или есть простой способ конвертировать мой 'original_class' в мой 'new_class', поскольку они абсолютно идентичны?

*** Правитьможет быть полезно добавить некоторый код для ясности (не мой настоящий код, просто представление того, чего я пытаюсь достичь)

Мой класс транзакций

public partial class Tran
{
    public string tranDescription
}

Мой класс ошибок транзакций

public partial class TranError
{
    public string tranDescription
}

Как я пытаюсь обработать ошибку

using(var db = new tranEntities())
{
    Tran t = new Tran();
    t.tranDescription = @"Some Description";
    try
    {
        db.Trans.Add(t);
    }
    catch (System.Data.Entity.Infrastructure.DbUpdateException)
    {
        db.TransError.Add(t);
    }
}

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

Ответы [ 3 ]

2 голосов
/ 24 сентября 2019

Вы можете создать метод, который возвращает новый объект как:

public ErrorObject ConvertToErrorObject(OriginalObject originalObject)
{
    var errorObject = new ErrorObject();
    errorObject.Property1 = originalObject.Property1;
    errorObject.Property2 = originalObject.Property2;

    return errorObject;
}

Затем просто сохраните объект ошибки как обычно.

Если это происходит с несколькими типами, вы можете сделать универсальныйметод, который использует отражение и проходит через свойства OriginalObject, получает там значения и устанавливает их в свойствах ErrorObject с тем же именем.

Общий метод (свойства с одинаковыми именами должны быть одного типа):

    public static Tout CloneAndCast<Tin, Tout>(Tin source)
        where Tin : class
        where Tout : class, new()
    {
        if(source != null)
        {
            var clone = new Tout();

            IEnumerable<PropertyInfo> membersIn = typeof(Tin).GetProperties();
            PropertyInfo[] membersOut = typeof(Tout).GetProperties();

            foreach(PropertyInfo member in membersIn)
            {
                membersOut.FirstOrDefault(o => o.Name == member.Name)?.SetValue(clone, member.GetValue(source));
            }

            return clone;
        }
        else
        {
            return null;
        }
    }
1 голос
/ 25 сентября 2019

Альтернатива ответу Томислава: если ваш проект использует JSON, вы можете переключать идентичные типы, используя сериализацию JSON:

public static class SwapperExtensions
{
    public static T2 Swap<T1,T2>(this T1 original) where T1:class where T2:class,new()
    {
        if (original == null)
            return null;

        try
        {
            var result = JsonConvert.SerializeObject(original);
            var newObject = JsonConvert.DeserializeObject<T2>(result);
            return newObject;
        }
        catch(Exception ex)
        {
            throw new ArgumentException("The provided types could not be swapped. See inner exception for details.", ex);
        }
    }
}

, которая выглядит следующим образом:

var tran = new Tran { TranDescription = "Some description." };

// do stuff...

var tranError = tran.Swap<Tran, TranError>();

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

1 голос
/ 24 сентября 2019

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

public class TranBaseClass {
     public string tranDescription
     // other properties
}

Тогда и Tran, и TranError могут наследовать от них:

public partial class Tran : TranBaseClass {}

public partial class TranError : TranBaseClass {} 

Затем я бы создал конструкторы для Tran и TranError, которые принимали бы базовый класс в качестве параметра:

var tran = new Tran(TranBaseClass)
var tranError = new Tran(TranBaseClass)

И ваш код мог бы выглядеть примерно так:

using(var db = new tranEntities())
{
    var t = new TranBaseClass();
    t.tranDescription = @"Some Description";
    try
    {
        db.Trans.Add(new Tran(t));
    }
    catch (System.Data.Entity.Infrastructure.DbUpdateException)
    {
        db.TransError.Add(new TranError(t));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...