AWS API: как преобразовать результат динамо в класс

Итак, у меня есть репозиторий моделей, в котором используется C # AWS SDK для Dynamo. Сейчас это немного некрасиво. Я бы хотел отбросить элементы результатов в свою модель. Попасть в «Динамо» - это здорово. Я просто размышляю над своими классами Poco и вставляю их вот так:

     var doc = new Document();
     foreach (PropertyInfo prop in model.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
     {
         var propName = (string)prop.Name;
         // dont add if value is null
         if (prop.GetValue(model, null) != null)
         {
             if (prop.PropertyType == typeof(string))
                 doc[propName] = (string)prop.GetValue(model, null);
             if (prop.PropertyType == typeof(List<string>))
                 doc[propName] = (List<string>)prop.GetValue(model, null);
             if (prop.PropertyType == typeof(float))
                 doc[propName] = (float)prop.GetValue(model, null);
         }
     }

Но здесь, в репозитории, я бы не хотел писать это уродливое ручное приведение при извлечении элементов. Есть ли помощник AWS, чтобы сделать это менее ручным? Думаю, я мог бы написать обратный цикл выше и получить имена свойств атрибутов, а затем проверить на null для каждого типа N, S, SS и т. д.

var request = new ScanRequest
            {
                TableName = TableName.User,
            };

            var response = client.Scan(request);
            var collection = (from item in response.ScanResult.Items
                from att in item
                select new User(att.Value.S, att.Value.N, att.Value.S, att.Value.N, att.Value.S, att.Value.S, att.Value.S, att.Value.S, att.Value.S,
                    att.Value.S, att.Value.S, att.Value.S, att.Value.S, att.Value.SS, att.Value.SS)).ToList();

            return collection.AsQueryable();

person FlavorScape    schedule 17.02.2013    source источник


Ответы (5)


Вы можете использовать функцию модели сохраняемости объекта в .NET SDK . Это позволяет аннотировать свои .NET-объекты атрибутами, которые затем определяют SDK, как эти данные должны храниться в DynamoDB.

person Pavel Safronov    schedule 19.02.2013
comment
Модель сохраняемости объекта не поддерживает разбиение на страницы. Если вам это нужно, похоже, вам нужно использовать другие модели (документ или низкий уровень), как подтверждено в этой статье aws.amazon.com/blogs/developer/ - person Luke; 06.02.2020

Вы можете использовать встроенный метод FromDocument для преобразования Dictionary<string, AttributeValue> в ваш класс типа T

List<MyClass> result = new List<MyClass>();

var response = await client.QueryAsync(request);

        foreach (Dictionary<string, AttributeValue> item in response.Items)
        {
            var doc = Document.FromAttributeMap(item);
            var typedDoc = context.FromDocument<MyClass>(doc);
            result.Add(typedDoc);
        }
person Vikash Rathee    schedule 08.11.2019
comment
Каков контекст в вашем примере? Откуда это взялось? - person Kamarey; 18.01.2021
comment
@Kamarey, контекст - это экземпляр DynamoDBContext. пример docs.aws.amazon.com/amazondynamodb/latest/developerguide/ < / а> - person Faishal Ahammad; 07.07.2021

В итоге я сделал это ЛООООООНГ. Было довольно забавно использовать отражение типа для создания собственной функции приведения типов. Было бы веселее, если бы не два часа ночи.

Ответ Павла более официальный, но он по-прежнему работает как шарм.

public static T ResultItemToClass<T>(Dictionary<string, AttributeValue> resultItem) where T : new()
        {
            var resultDictionary = new Dictionary<string, object>();

            Type type = typeof(T);
            T ret = new T();

            foreach (KeyValuePair<string, AttributeValue> p in resultItem)
                if (p.Value != null)
                    foreach (PropertyInfo prop in p.Value.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
                        if (prop.GetValue(p.Value, null) != null)              
                            {
                                if (prop.Name == "S")
                                    type.GetProperty(p.Key).SetValue(ret, prop.GetValue(p.Value, null), null);                                    

                                if (prop.Name == "SS")
                                    type.GetProperty(p.Key).SetValue(ret, (List<string>)prop.GetValue(p.Value, null), null);

                                if (prop.Name == "N")
                                    type.GetProperty(p.Key).SetValue(ret,  Convert.ToInt32(prop.GetValue(p.Value, null)), null);

                                // TODO: add some other types. Too tired tonight
                            }                           
            return ret;
        }
person FlavorScape    schedule 21.02.2013
comment
Как мы можем установить это для prop.Name == M? - person Viral Sarvaiya; 14.11.2017

Из класса результатов aws Document вы можете использовать метод экземпляра: .ToJson (), а затем десериализовать его в свой класс.

person Andrei Gec    schedule 09.06.2017
comment
Этот ответ требует некоторой доработки, и, как уже говорилось, постоянство объекта будет работать намного лучше. - person Brendon Bezuidenhout; 17.08.2017

Универсальный метод преобразует таблицу Dynamo в класс C # как функцию расширения.

public static List<T> ToMap<T>(this List<Document> item)
    {
        List<T> model = (List<T>)Activator.CreateInstance(typeof(List<T>));
        foreach (Document doc in item)
        {
            T m = (T)Activator.CreateInstance(typeof(T));
            var propTypes = m.GetType();
            foreach (var attribute in doc.GetAttributeNames())
            {
                var property = doc[attribute];
                if (property is Primitive)
                {
                    var properties = propTypes.GetProperty(attribute);
                    if (properties != null)
                    {
                        var value = (Primitive)property;
                        if (value.Type == DynamoDBEntryType.String)
                        {
                            properties.SetValue(m, Convert.ToString(value.AsPrimitive().Value));
                        }
                        else if (value.Type == DynamoDBEntryType.Numeric)
                        {
                            properties.SetValue(m, Convert.ToInt32(value.AsPrimitive().Value));
                        }
                    }
                }
                else if (property is DynamoDBBool)
                {
                    var booleanProperty = propTypes.GetProperty(attribute);
                    if (booleanProperty != null)
                        booleanProperty.SetValue(m, property.AsBoolean());
                }
            }
            model.Add(m);
        }
        return model;
    } 
person Sher Singh    schedule 07.11.2020