Проблема с простым маппингом
От: Аноним  
Дата: 29.05.09 08:38
Оценка:
Помогите добиться нужного поведения: в источнике данных есть поле, название которого совпадает с названием свойства класса, но замапить его нужно на другое свойство.
public class Object1
{
    [MapField("col2")]
    public int Col1 { get; set; }
}

[TestMethod]
public void Test()
{
    DataTable dt = new DataTable();
    dt.Columns.Add("col1", typeof(int));
    dt.Columns.Add("col2", typeof(int));
    dt.Rows.Add(1, 2);

    Object1 o = Map.DataRowToObject<Object1>(dt.Rows[0]);
    Assert.AreEqual(2, o.Col1);
}


Падает на выделенной строке.
BLToolkit.Mapping.MappingException: Wrong mapping field name: 'col1', type: 'Object1'. Use field name 'col2' instead.


Очень хорошая библиотека, спасибо.
Re: Проблема с простым маппингом
От: IT Россия linq2db.com
Дата: 01.06.09 03:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Падает на выделенной строке.

А>BLToolkit.Mapping.MappingException: Wrong mapping field name: 'col1', type: 'Object1'. Use field name 'col2' instead.

Регистр имеет значение. Нужно, чтобы везде было либо col1, либо Col1.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Проблема с простым маппингом
От: Linguru  
Дата: 01.06.09 11:15
Оценка:
Здравствуйте, IT, Вы писали:

А>>Падает на выделенной строке.

А>>BLToolkit.Mapping.MappingException: Wrong mapping field name: 'col1', type: 'Object1'. Use field name 'col2' instead.

IT>Регистр имеет значение. Нужно, чтобы везде было либо col1, либо Col1.


Не помогло. Дело не в регистре. Похоже на то, что так оно и планировалось.

При вызове ObjectMapper["col1"] в строке (1) мы получаем маппер "col1" -> Col1.
Затем в строке (2) выясняем, что у Col1 уже есть другой маппер, и выбрасываем исключение.
Почему выбрасываем исключение, а не возвращаем null?


class ObjectMapper {
public  MemberMapper this[string name]
{
    get
    {
        if (name == null) throw new ArgumentNullException("name");

        MemberMapper mm = (MemberMapper)_nameToMember[name];

        if (mm == null)
        {
            lock (_nameToMember.SyncRoot)
            {
                mm = (MemberMapper)_nameToMember[name];

                if (mm == null)
                {
                    mm = (MemberMapper)_nameToMember[name.ToLower(CultureInfo.CurrentCulture)];

                    if (mm == null)
                    {
                        mm = GetComplexMapper(name, name); // (1)

                        if (mm != null)
                        {
                            if (_members.Contains(mm)) // (2)
                                throw new MappingException(string.Format(
                                    "Wrong mapping field name: '{0}', type: '{1}'. Use field name '{2}' instead.",
                                    name, _typeAccessor.OriginalType.Name, mm.Name));

                            Add(mm);
                        }
                    }
                    else
                        _nameToMember[name] = mm;
                }
            }
        }

        return mm;
    }
}


//Совсем не критично, в конце концов я могу свойство переименовать, но лучше, если не придется этого делать.
Re[3]: Проблема с простым маппингом
От: ili Россия  
Дата: 01.06.09 12:38
Оценка:
Здравствуйте, Linguru, Вы писали:

L>//Совсем не критично, в конце концов я могу свойство переименовать, но лучше, если не придется этого делать.


ИМХО это очень хитрый и полезный в большинстве случаев финт. не дает запутаться — в маппинге всегда пользуются алиасы объектов. в большинатве случаев, а в особенности примеров, имя алиаса совпадает с именем свойства\поля, и как-то с ходу, бывает не поймешь что пользовать, а тут тебе просто не дают пользовать "не то"...
Re[4]: Проблема с простым маппингом
От: Linguru  
Дата: 01.06.09 13:48
Оценка:
Здравствуйте, ili, Вы писали:

ili>Здравствуйте, Linguru, Вы писали:


L>>//Совсем не критично, в конце концов я могу свойство переименовать, но лучше, если не придется этого делать.


ili>ИМХО это очень хитрый и полезный в большинстве случаев финт. не дает запутаться — в маппинге всегда пользуются алиасы объектов. в большинатве случаев, а в особенности примеров, имя алиаса совпадает с именем свойства\поля, и как-то с ходу, бывает не поймешь что пользовать, а тут тебе просто не дают пользовать "не то"...


Не верю. Это противоречит философии библиотеки Я явно указываю, что на что мапить. Почему кто-то за меня решил, что это "не то"?
Со времен rfd такого не бывало.
Re[5]: Проблема с простым маппингом
От: ili Россия  
Дата: 02.06.09 03:06
Оценка:
Здравствуйте, Linguru, Вы писали:

L>Не верю. Это противоречит философии библиотеки Я явно указываю, что на что мапить. Почему кто-то за меня решил, что это "не то"?


эмн... вот что интересно...
обджект маппер не найдя среди мембер мапперов "Col1" попробует определить его через GetComplexMapper(...)... последний ни мало сумнявшись найдет маппер на поле "Col1" у которого алиас "col2"... так вот, если убрать эксепшн вылетит новый — при попытке добавить этот маппер к списку — мол ключ уже добавлен... можно, конечно, сделать так:

mm = GetComplexMapper(name, name);

if (mm != null)
{
    if (_nameToMember.ContainsKey(mm.Name))
        return mm;

    if (_members.Contains(mm))
        throw new MappingException(string.Format(
            "Wrong mapping field name: '{0}', type: '{1}'. Use field name '{2}' instead.",
            name, _typeAccessor.OriginalType.Name, mm.Name));

    Add(mm);
}


но желаемого эффекта мы не молучим, вот такой тест — провалится:

[Test]
public void NameTest2()
{
    DataTable dt = new DataTable();
    dt.Columns.Add("col2", typeof(int));
    dt.Columns.Add("col1", typeof(int));
    dt.Rows.Add(2, 1);

    Object4 o = Map.DataRowToObject<Object4>(dt.Rows[0]);
    Assert.AreEqual(2, o.Col1);
}


от оригинального я тут поменял порядок колонок, и сначала в поле "Col1" смапилось значение из столбца "col2" а потом из столбца "col1"

чтобы этого избежать, надо возвращать null, скажем так:
mm = GetComplexMapper(name, name);

if (mm != null)
{
    if (_nameToMember.ContainsKey(mm.Name))
        return null;

    if (_members.Contains(mm))
        throw new MappingException(string.Format(
            "Wrong mapping field name: '{0}', type: '{1}'. Use field name '{2}' instead.",
            name, _typeAccessor.OriginalType.Name, mm.Name));

    Add(mm);
}


или вообще вместо эксепшена... но наскока это черевато — я
Re[6]: Проблема с простым маппингом
От: Linguru  
Дата: 02.06.09 05:06
Оценка:
Здравствуйте, ili, Вы писали:

ili>или вообще вместо эксепшена... но наскока это черевато — я


Чревато тем, что ломается вот этот тест: Mapping.ResultSetTest.TestFailResultSet1().
Все остальное работает, и мой сценарий.
Re[7]: Проблема с простым маппингом
От: ili Россия  
Дата: 02.06.09 08:54
Оценка:
Здравствуйте, Linguru, Вы писали:

L>Здравствуйте, ili, Вы писали:


ili>>или вообще вместо эксепшена... но наскока это черевато — я


L>Чревато тем, что ломается вот этот тест: Mapping.ResultSetTest.TestFailResultSet1().

L>Все остальное работает, и мой сценарий.

ну... тык оно прямо его и ожидает... можно сказать задокументированное поведение
вообще, то что только тест валится, это не показатель, этот тест зачем-то добавлен и что-то перекрывает.
судя по логу ввод этого эксепшена едва ли не багфикс, так что можно ли его безболезненно менять null-ом?... вот IT придет, пускай расскажет, если вспомнит а если не вспомнит, то, думаю, можно и заменить...
Re[8]: Проблема с простым маппингом
От: Linguru  
Дата: 02.06.09 20:15
Оценка:
Здравствуйте, ili, Вы писали:

ili>ну... тык оно прямо его и ожидает... можно сказать задокументированное поведение

ili>вообще, то что только тест валится, это не показатель, этот тест зачем-то добавлен и что-то перекрывает.
ili>судя по логу ввод этого эксепшена едва ли не багфикс, так что можно ли его безболезненно менять null-ом?... вот IT придет, пускай расскажет, если вспомнит а если не вспомнит, то, думаю, можно и заменить...

Я засомневался в корректности этого теста.
Илья, можешь проверить одну вещь, пока IT нет? Закомментируй [ExpectedException(typeof(MappingException))] в TestFailResultSet1() и посмотри, какое исключение будет. Никаких изменений в ObjectMapper вносить не нужно.

Дело в том, что там нет MappingException, а есть ArgumentException. Но NUnit это устраивает почему-то. Может, я что-то не так делаю, давно NUnit не использовал.
Вот, что мне VS Test выдает там, где NUnit срабатывает:

Error Message:
Test method TestProject1.UnitTest1.TestFailResultSet1 threw exception System.ArgumentException, but exception BLToolkit.Mapping.MappingException was expected. Exception message: System.ArgumentException: Элемент уже добавлен. Ключ в словаре: "masterid" Добавляемый ключ: "masterid"

Error Stack Trace:
System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
System.Collections.Hashtable.Add(Object key, Object value)
BLToolkit.Mapping.ObjectMapper.Add(MemberMapper memberMapper) in C:\Projects\BlToolkit 3.2\Source\Mapping\ObjectMapper.cs: line 85
BLToolkit.Mapping.ObjectMapper.get_Item(String name) in C:\Projects\BlToolkit 3.2\Source\Mapping\ObjectMapper.cs: line 173
BLToolkit.Mapping.ObjectMapper.GetValue(Object o, String name) in C:\Projects\BlToolkit 3.2\Source\Mapping\ObjectMapper.cs: line 500
BLToolkit.Mapping.MapIndex.GetValue(IMapDataSource source, Object obj, Int32 index) in C:\Projects\BlToolkit 3.2\Source\Mapping\MapIndex.cs: line 72
BLToolkit.Mapping.MapIndex.GetValueOrIndex(IMapDataSource source, Object obj) in C:\Projects\BlToolkit 3.2\Source\Mapping\MapIndex.cs: line 97
BLToolkit.Mapping.MappingSchema.MapResultSets(MapResultSet[] resultSets) in C:\Projects\BlToolkit 3.2\Source\Mapping\MappingSchema.cs: line 3438
BLToolkit.Mapping.MappingSchema.MapDataReaderToResultSet(IDataReader reader, MapResultSet[] resultSets) in C:\Projects\BlToolkit 3.2\Source\Mapping\MappingSchema.cs: line 3533
BLToolkit.Data.DbManager.ExecuteResultSet(MapResultSet[] resultSets) in C:\Projects\BlToolkit 3.2\Source\Data\DbManager.cs: line 3887
TestProject1.UnitTest1.TestFailResultSet1() in C:\Projects\BlToolkit 3.2\TestProject1\UnitTest1.cs: line 120



А вот если убрать исключение из ObjectMapper, то TestFailResultSet1() исключение не словит, а структура объектов в этом тесте заполнится правильно.
Поэтому я и засомневался в этом тесте. Может он устарел?
До конца ситуацию не понимаю, но что-то тут не так
Re[9]: Проблема с простым маппингом
От: ili Россия  
Дата: 03.06.09 04:06
Оценка:
Здравствуйте, Linguru, Вы писали:

L>Здравствуйте, ili, Вы писали:


L>Я засомневался в корректности этого теста.

L>Илья, можешь проверить одну вещь, пока IT нет? Закомментируй [ExpectedException(typeof(MappingException))] в TestFailResultSet1() и посмотри, какое исключение будет. Никаких изменений в ObjectMapper вносить не нужно.

не обманывай меня чтобы получить этот эксепшн нужно как раз закомментировать выброс MappingException
твой изначальный тест в этой ситуации выкинет ровно такой же эксепшн. а разное поведение у тебя, по ходу из-за того, что для студийной гоялки тестов достаточно пеесобрать проект UnitTests.CS, а для НЮнита нужен UnitTests.All

как я писал выше, не найдя мембер маппер по алиасу обджек маппер через метод GetComplexMapper(...) найдет его по имени поля\свойства. далее он честно попытается его добавить в список своих мембер мапперов, и вот тут-то это и не получится — ведь там уже есть именно этот мембер маппер который, о чем, соственно и говорит эксепшн, мол нельзя, мембер маппер с таким алиасом уже есть.
по ходу пьессы именно от этой ситуации и стоит выброс MappingException.

покамест, единственное разумное, что приходит в голову — вертать null вместо эсепшена... вроде все гладко получается...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.