powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Object-object mapping
23 сообщений из 23, страница 1 из 1
Object-object mapping
    #37029679
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть ли ещё библиотечки наподобие AutoMapper?
Мне конкретно надо конвертировать типизированный датасет в POCO и обратно.
...
Рейтинг: 0 / 0
Object-object mapping
    #37029731
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если Linq to DataSet заюзать? Или я чего ен понял.
...
Рейтинг: 0 / 0
Object-object mapping
    #37029782
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
class A { string a; }
class MySet: DataSet
{
ATable AObjects;
... ну и так далее ...
}

и как?
...
Рейтинг: 0 / 0
Object-object mapping
    #37029823
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Object-object mapping
    #37030301
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maXmoЕсть ли ещё библиотечки наподобие AutoMapper?
Мне конкретно надо конвертировать типизированный датасет в POCO и обратно.
Мне понравился вот этот (идеей, лично не юзал).
...
Рейтинг: 0 / 0
Object-object mapping
    #37030960
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qu-quМне понравился вот этот (идеей, лично не юзал).
А какая там идея? Банальный конверт. На нём далеко не уедешь, если и делать что-то универсальное, что, наверное, на аттрибутах destination классов. Ну а простенькие конверты мало кому интересны.
...
Рейтинг: 0 / 0
Object-object mapping
    #37033873
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУqu-quМне понравился вот этот (идеей, лично не юзал).
А какая там идея? Банальный конверт. На нём далеко не уедешь, если и делать что-то универсальное, что, наверное, на аттрибутах destination классов. Ну а простенькие конверты мало кому интересны.

Там "конверт" только для встроенных типов CLR, а для юзерских классов, массивов, IDictionary<string,object> и пр. IDataRecord-ов - там "честная" автогенерация лямбд-делегатов по метаданным из Reflection + если свойства не резолвятся напрямую по именам (включая ссылочные иерархии типа: "source1.Client.ID" -> "destination1.ClientID"), то можно добавить свою кастомную лямбду, которая будет доопределять нестыковки (но не конвертить напрямую, а дописываться/встраиваться к уже сгенеренной "основной" лямбде).
Ну и, понятное дело, все кешируется на статическом уровне (кажися?), т.е. достаточно 1 раз использовать маппер между определенными типами и оно потом в остальных вызовах будет просто "летать"...
(разница в скорости вызова прямого метода и скомпиленной лямбды - 2-3ms).
...
Рейтинг: 0 / 0
Object-object mapping
    #37034044
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qu-qu, какая нафиг честная автогенерация лямбд. На простой задаче DataTable => Class нужно самому писать лямбду:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
var table = new DataTable();
table.Columns.AddRange(new DataColumn[] { new DataColumn("ID", typeof(int)), new DataColumn("FirstName") });
table.Rows.Add(1, "Тест1");
table.Rows.Add(2, "Тест2");
table.Rows.Add(3, "Тест3");

var mapper = Mapper.Create<DataRow, Human>(d => new Human { ID = d.Field<int>("ID"), FirstName = d.Field<string>("FirstName") });
var list = table.AsEnumerable().Select(d => mapper.Invoke(d));

Вот и спрашивается, на кой мне такая "честность", ведь на описание маппера мне приходится делать то же приведение, которое я бы и так делал.
...
Рейтинг: 0 / 0
Object-object mapping
    #37034087
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Object-object mapping
    #37034097
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сцуко, даже DataRowAdapter не хавает:

DataRowAdapter
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
public class DataRowAdapter : IDataRecord
{
    #region Members
    private DataRow _Row;
    #endregion

    #region Properties
    public DataRow Row
    {
        get { return _Row; }
    }
    #endregion

    #region Constructors
    public DataRowAdapter(DataRow row)
    {
        _Row = row;
    }
    #endregion

    #region IDataRecord Implementation
    public object this[string name]
    {
        get { return _Row[name]; }
    }

    public object this[int i]
    {
        get { return _Row[i]; }
    }

    public int FieldCount
    {
        get { return _Row.Table.Columns.Count; }
    }

    public bool GetBoolean(int i)
    {
        return Convert.ToBoolean(_Row[i]);
    }

    public byte GetByte(int i)
    {
        return Convert.ToByte(_Row[i]);
    }

    public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
    {
        throw new NotSupportedException("GetBytes is not supported.");
    }

    public char GetChar(int i)
    {
        return Convert.ToChar(_Row[i]);
    }

    public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    {
        throw new NotSupportedException("GetChars is not supported.");
    }

    public IDataReader GetData(int i)
    {
        throw new NotSupportedException("GetData is not supported.");
    }

    public string GetDataTypeName(int i)
    {
        return _Row[i].GetType().Name;
    }

    public DateTime GetDateTime(int i)
    {
        return Convert.ToDateTime(_Row[i]);
    }

    public decimal GetDecimal(int i)
    {
        return Convert.ToDecimal(_Row[i]);
    }

    public double GetDouble(int i)
    {
        return Convert.ToDouble(_Row[i]);
    }

    public Type GetFieldType(int i)
    {
        return _Row[i].GetType();
    }

    public float GetFloat(int i)
    {
        return Convert.ToSingle(_Row[i]);
    }

    public Guid GetGuid(int i)
    {
        return (Guid)_Row[i];
    }

    public short GetInt16(int i)
    {
        return Convert.ToInt16(_Row[i]);
    }

    public int GetInt32(int i)
    {
        return Convert.ToInt32(_Row[i]);
    }

    public long GetInt64(int i)
    {
        return Convert.ToInt64(_Row[i]);
    }

    public string GetName(int i)
    {
        return _Row.Table.Columns[i].ColumnName;
    }

    public int GetOrdinal(string name)
    {
        return _Row.Table.Columns.IndexOf(name);
    }

    public string GetString(int i)
    {
        return _Row[i].ToString();
    }

    public object GetValue(int i)
    {
        return _Row[i];
    }

    public int GetValues(object[] values)
    {
        values = _Row.ItemArray;
        return _Row.ItemArray.GetLength(0);
    }

    public bool IsDBNull(int i)
    {
        return Convert.IsDBNull(_Row[i]);
    }
    #endregion
}


Ну и на кой хер (с) нам такие гавномапперы?
...
Рейтинг: 0 / 0
Object-object mapping
    #37034134
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУqu-qu, какая нафиг честная автогенерация лямбд. На простой задаче DataTable => Class нужно самому писать лямбду...

Значит, чувак поленился реализовать сценарии работы с данными (IDictionary, IDataRecord и пр. получается - были моими фантазиями).
(но я же честно написал - сам не юзал, но идея - понравилась, потому, наверное, и фантазия разыгралась).

Если так уж надо "DataTable => Class" - почему бы не записаться в "контрибьюторы" проекта и дописать недостающее самому?
(на том и стоит OSS).

З.Ы. или стырить по-тихому идею и добавить в свою реализацию все, что угодно... (или нужно на данный момент).
...
Рейтинг: 0 / 0
Object-object mapping
    #37034140
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУСцуко, даже DataRowAdapter не хавает:

+
DataRowAdapter


Ну и на кой хер (с) нам такие гавномапперы?

Это ты ему пытался свой адаптер скормить?
Или где-то в недрах его кода нашел "болванку" для IDataRecord?
...
Рейтинг: 0 / 0
Object-object mapping
    #37034154
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qu-quфантазия разыгралась
Херасе у Вас фантазии:

- "честная" автогенерация лямбд-делегатов
- по метаданным из Reflection типа идёт работа
- все кешируется на статическом уровне
- разница в скорости вызова прямого метода и скомпиленной лямбды - 2-3ms



Тут либо плюмбум либо люминий.

P.S.

qu-quесли свойства не резолвятся напрямую по именам (включая ссылочные иерархии типа: "source1.Client.ID" -> "destination1.ClientID"), то можно добавить свою кастомную лямбду
Грошь цена мапперу, который не предоставляет этот функционал :)

qu-quпочему бы не записаться в "контрибьюторы" проекта и дописать недостающее самому?
Неее, в топку. Пусть пацанва сама свои грабли собирает.

qu-quЗ.Ы. или стырить по-тихому идею и добавить в свою реализацию все, что угодно... (или нужно на данный момент).
Это всегда можно )
...
Рейтинг: 0 / 0
Object-object mapping
    #37034162
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qu-quЭто ты ему пытался свой адаптер скормить?
Или где-то в недрах его кода нашел "болванку" для IDataRecord?
Ну как бы да, пытался адаптер скормить, чтоб IDataRecord кушал.
Можно и расширение енумерабловое накидать:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
public static IEnumerable<IDataRecord> Enumerate(this IDataReader reader)
{
    using (reader)
    {
        while (reader.Read())
        {
            yield return reader;
        }
    }
}

... но всё-равно нихрена не умеет работать. Болванка не недровая, простой глупый адаптер.
Поэтому, смело пакуем маппер в корзину с прокисшими помидорами.
...
Рейтинг: 0 / 0
Object-object mapping
    #37034192
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А в случае автомаппера всё выглядит просто:

Код: plaintext
1.
2.
Mapper.Reset(); 
Mapper.CreateMap<IDataReader, Human>();
var results = Mapper.Map<IDataReader, List<Human>>(table.CreateDataReader());

Human
Код: plaintext
1.
2.
3.
4.
public class Human
{
    public int ID { get; set; }
    public string FirstName { get; set; }
}


Ну не красота-ли, qu-qu?
...
Рейтинг: 0 / 0
Object-object mapping
    #37034222
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУА в случае автомаппера всё выглядит просто:

Код: plaintext
1.
2.
Mapper.Reset(); 
Mapper.CreateMap<IDataReader, Human>();
var results = Mapper.Map<IDataReader, List<Human>>(table.CreateDataReader());

+
Human
Код: plaintext
1.
2.
3.
4.
public class Human
{
    public int ID { get; set; }
    public string FirstName { get; set; }
}


Ну не красота-ли, qu-qu?

Красота-то красота (кто бы спорил), только я бы все-таки "разорился" на 1 extension method:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
...
public static T MapTo<T>(this IDataReader reader) {
   return Mapper.Map<IDataReader, T>(reader);
}
...
var results = table.CreateDataReader().MapTo<List<Human>>();
...

З.Ы. мне близки также идеи Fluent Interface...
...
Рейтинг: 0 / 0
Object-object mapping
    #37034228
qu-qu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУ,

Кстати, насчет этого:
Код: plaintext
1.
2.
Mapper.Reset(); 
Mapper.CreateMap<IDataReader, Human>();
Не находишь ли ты эти 2 строчки - "церемониальными" и "словообильными"?
(на одно действие по маппингу - 2 действия по подготовке маппера, по-моему, многовато).
...
Рейтинг: 0 / 0
Object-object mapping
    #37034291
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qu-qu, ну Reset можно не юзать (это так, кеши подрихтовать), а на счёт CreateMap => Map согласен, криво сделано. Но это всё касается IDataReader/IDataRecord. Для "обычных" телодвижений подойдёт просто Map.
...
Рейтинг: 0 / 0
Object-object mapping
    #37132999
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зацените, написал маппер. Сторонние либы использовать не желательно в проектах. Работает на Runtime.CompilerServices, достаточно шустр. От лямбды отказался, не хотелось промежуточные бизнес интерфесы плодить.
Может кому понадобится, а еще лучше, если кто-то свою лепту внесёт :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
// Тесты
var table = new DataTable();
table.Columns.AddRange(new DataColumn[] { 
    new DataColumn("ID", typeof(int)), 
    new DataColumn("FirstName"),
    new DataColumn("FooY"),
    new DataColumn("Foo1", typeof(int)), 
});
table.Rows.Add(1, "Тест1", "qwerty", 7);
table.Rows.Add(2, "Тест2", "qwertyddd", 77);
table.Rows.Add(3, "Тест3", "qwertyasa", null);

var test1 = DataMapper.Map<Human>(table);
var test2 = DataMapper.Map<Human>(table,
    (a, b) => new { a.FooX, f = "FooY" }, 
    (a, b) => new { a.Foo2, f = "Foo1" }
);

Proxi
Код: plaintext
1.
2.
3.
4.
5.
6.
public class Human
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string FooX { get; set; }
    public int? Foo2 { get; set; }
}


DataMapper
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
/// <summary>
/// Маппер
/// </summary>
public class DataMapper
{
    /// <summary>
    /// Выбор сопоставления из словаря
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="expressions"></param>
    /// <returns></returns>
    private static string ResolveSchema(string columnName, Dictionary<string, string> expressions)
    {
        string result = columnName;
        if (expressions.ContainsKey(columnName))
        {
            result = expressions[columnName];
        }
        return result;
    }

    /// <summary>
    /// Словарь сопоставлений
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <param name="schema"></param>
    /// <returns></returns>
    private static Dictionary<string, string> ResolveExpression<T>(T obj, Expression<Func<T, object, object>>[] schema)
    {
        var result = new Dictionary<string, string>();
        foreach (var sch in schema)
        {
            var compile = sch.Compile()(obj, null);
            var value = compile.GetType().GetProperties()[1].GetValue(compile, null);
            result.Add(value.ToString(), (sch.Body as NewExpression).Members[0].Name);
        }
        return result;
    }

    /// <summary>
    /// Маппинг DataRow
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="row"></param>
    /// <returns></returns>
    public static T Map<T>(DataRow row, params Expression<Func<T, object, object>>[] schema) where T : new()
    {
        T result = new T();
        var expressions = ResolveExpression<T>(result, schema);

        foreach (DataColumn column in row.Table.Columns)
        {
            string propname = ResolveSchema(column.ColumnName, expressions);

            var property = typeof(T).GetProperty(propname);
            if (property != null)
            {
                TypeCode codeObj = property.PropertyType.IsGenericType ?
                    Type.GetTypeCode(property.PropertyType.GetGenericArguments()[0]) :
                    Type.GetTypeCode(property.PropertyType);

                TypeCode codeRow = Type.GetTypeCode(row[column.ColumnName].GetType());

                if (codeObj == codeRow)
                {
                    object value = row[column.ColumnName] == DBNull.Value ? null : row[column.ColumnName];
                    property.SetValue(result, value, null);
                }
            }
        }
        return result;
    }

    /// <summary>
    /// Маппинг DataTable
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="table"></param>
    /// <returns></returns>
    /// <example>
    /// var list = DataMapper.Map<BusinessClass>(table,
    ///        (a, b) => new { a.PropertyForMapA, f = "PropertyForMap1" }, 
    ///        (a, b) => new { a.PropertyForMapB, f = "PropertyForMap2" }
    ///    );
    /// </example>
    public static IEnumerable<T> Map<T>(DataTable table, params Expression<Func<T, object, object>>[] schema) where T : new()
    {
        return table.AsEnumerable().Select(d => Map<T>(d, schema));
    }

    /// <summary>
    /// Маппинг IDataReader
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="reader"></param>
    /// <param name="schema"></param>
    /// <returns></returns>
    public static IEnumerable<T> Map<T>(IDataReader reader, params Expression<Func<T, object, object>>[] schema) where T : new()
    {
        DataTable table = new DataTable();
        table.Load(reader);
        return Map<T>(table, schema);
    }
}
...
Рейтинг: 0 / 0
Object-object mapping
    #37136730
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Грят, мапер через рефлексию - это не айс.
...
Рейтинг: 0 / 0
Object-object mapping
    #37136731
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ах, да, я остановился на EmitMappere.
...
Рейтинг: 0 / 0
Object-object mapping
    #37136924
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maXmoГрят, мапер через рефлексию - это не айс.
Ну там не только рефлекшен, есть и Expression ;)

maXmoАх, да, я остановился на EmitMappere.
Ага, читал про его скорость тут .

P.S. Сторонние либы не юзаем в проектах, поэтому пришлось своё простенькое написать для текущих задач.
...
Рейтинг: 0 / 0
Object-object mapping
    #37545273
Фотография Роман Дынник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как с EmitMapper сделать мэппинг типа
Код: plaintext
1.
2.
bo.Product.Name=>dto.ProductName
//и обратно 
dto.ProductName=>bo.Product.Name
?
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Object-object mapping
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]