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

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

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

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

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

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

+
DataRowAdapter


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

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

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



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

P.S.

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

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

qu-quЗ.Ы. или стырить по-тихому идею и добавить в свою реализацию все, что угодно... (или нужно на данный момент).
Это всегда можно )
...
Рейтинг: 0 / 0
24.12.2010, 15:50
    #37034162
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
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
24.12.2010, 16:03
    #37034192
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
А в случае автомаппера всё выглядит просто:

Код: 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
24.12.2010, 16:12
    #37034222
qu-qu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
МСУА в случае автомаппера всё выглядит просто:

Код: 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
24.12.2010, 16:15
    #37034228
qu-qu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
МСУ,

Кстати, насчет этого:
Код: plaintext
1.
2.
Mapper.Reset(); 
Mapper.CreateMap<IDataReader, Human>();
Не находишь ли ты эти 2 строчки - "церемониальными" и "словообильными"?
(на одно действие по маппингу - 2 действия по подготовке маппера, по-моему, многовато).
...
Рейтинг: 0 / 0
24.12.2010, 16:43
    #37034291
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
qu-qu, ну Reset можно не юзать (это так, кеши подрихтовать), а на счёт CreateMap => Map согласен, криво сделано. Но это всё касается IDataReader/IDataRecord. Для "обычных" телодвижений подойдёт просто Map.
...
Рейтинг: 0 / 0
24.02.2011, 09:16
    #37132999
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
Зацените, написал маппер. Сторонние либы использовать не желательно в проектах. Работает на 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
25.02.2011, 18:59
    #37136730
maXmo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
Грят, мапер через рефлексию - это не айс.
...
Рейтинг: 0 / 0
25.02.2011, 19:00
    #37136731
maXmo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
Ах, да, я остановился на EmitMappere.
...
Рейтинг: 0 / 0
25.02.2011, 21:28
    #37136924
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Object-object mapping
maXmoГрят, мапер через рефлексию - это не айс.
Ну там не только рефлекшен, есть и Expression ;)

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

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


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