Из одной строки поднимать два объекта.
От: QwErTys  
Дата: 05.12.05 14:01
Оценка:
Всем привет. Есть заморочка, нужна помощь по ее разморачиванию.

Дано.
Запрос.
select 
    a0.UserId a0_UserId, a0.Name a0_Name, 
    a1.ProjectId a1_ProjectId, a1.ProjectName a1_ProjectName 
from 
    [User] a0, Project a1

Классы.
public class User
{
    public int UserId;
    public string Name;
}

public class Project
{
    public int ProjectId;
    public string ProjectName;
}


Необходимо заморочиться и из каждой строки резалтсета, поднимать объект User и Project, можно ли это сделать c помощью RFD и если да, то какой кровью.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re: Из одной строки поднимать два объекта.
От: IT Россия linq2db.com
Дата: 05.12.05 14:24
Оценка: 3 (1)
Здравствуйте, QwErTys, Вы писали:

QET>Необходимо заморочиться и из каждой строки резалтсета, поднимать объект User и Project, можно ли это сделать c помощью RFD и если да, то какой кровью.


Можно примерно так:

using (DbManager   db = new DbManager())
using (IDataReader rd = db
    .SetCommand(...)
    .ExecuteReader())
{
    User    user    = new User();
    Project project = new Project();

    Map.ToObject(rd, user);
    Map.ToObject(rd, project);
}

По идее должно работать.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Из одной строки поднимать два объекта.
От: QwErTys  
Дата: 05.12.05 14:31
Оценка:
QET>>Необходимо заморочиться и из каждой строки резалтсета, поднимать объект User и Project, можно ли это сделать c помощью RFD и если да, то какой кровью.

IT>Можно примерно так:


IT>
IT>using (DbManager   db = new DbManager())
IT>using (IDataReader rd = db
IT>    .SetCommand(...)
IT>    .ExecuteReader())
IT>{
IT>    User    user    = new User();
IT>    Project project = new Project();

IT>    Map.ToObject(rd, user);
IT>    Map.ToObject(rd, project);
IT>}
IT>

IT>По идее должно работать.
Игорь, еще одни вопрос

-- Запрос может быть таким
select 
    a0.UserId a0_UserId, a0.Name a0_Name, 
    a1.ProjectId a1_ProjectId, a1.ProjectName a1_ProjectName 
from 
    [User] a0, Project a1
-- а может быть и таким
select 
    a0.ProjectId a1_ProjectId, a0.ProjectName a0_ProjectName 
    a1.UserId a1_UserId, a1.Name a1_Name, 

from 
    Project a0, [User] a1

Тоесть, альясы меняются динамически, что нужно сделать c RFD что бы ему в рантайме прописывать связи?
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[3]: Из одной строки поднимать два объекта.
От: IT Россия linq2db.com
Дата: 05.12.05 17:17
Оценка: 3 (1)
Здравствуйте, QwErTys, Вы писали:

QET>Тоесть, альясы меняются динамически, что нужно сделать c RFD что бы ему в рантайме прописывать связи?


Это уже сложнее. Можно поизвращаться с IMapDataReceiver.

public class MyReceiver : IMapDataReceiver
{
    public MyReceiver(Hashtable hash, object entity)
    {
        _receiver = Map.Descriptor(entity.GetType());
        _hash     = hash;
        _entity   = entity;
    }

    IMapDataReceiver _receiver;
    Hashtable        _hash;
    object           _entity;

    public int GetOrdinal (string name)
    {
        object mapName = _hash[name];

        if (mapName == null)
            name = mapName.ToString();

        return _receiver.GetOrdinal(name);
    }

    public void SetFieldValue(int i, string name, object entity, object value)
    {
        object mapName = _hash[name];

        if (mapName == null)
            name = mapName.ToString();

        _receiver.SetFieldValue(i, name, _entity, value);
    }
}


Hashtable mapNames = new Hashtable();

mapNames["a1_Name"] = "a0_Name";

using (DbManager   db = new DbManager())
using (IDataReader rd = db
    .SetCommand(...)
    .ExecuteReader())
{
    User    user    = new User();

    Project project = new Project();

    Map.ToObject(rd, new MyReceiver(mapnames, user));
    Map.ToObject(rd, project);
}
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: Из одной строки поднимать два объекта.
От: IT Россия linq2db.com
Дата: 05.12.05 17:19
Оценка:
Здравствуйте, IT, Вы писали:

QET>>Тоесть, альясы меняются динамически, что нужно сделать c RFD что бы ему в рантайме прописывать связи?


IT>Это уже сложнее. Можно поизвращаться с IMapDataReceiver.


Можно ещё сам объект наследовать от этого интерфейса, тогда не надо будет создавать промежуточный.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Из одной строки поднимать два объекта.
От: QwErTys  
Дата: 06.12.05 06:12
Оценка:
QET>>Необходимо заморочиться и из каждой строки резалтсета, поднимать объект User и Project, можно ли это сделать c помощью RFD и если да, то какой кровью.

IT>Можно примерно так:


IT>
IT>using (DbManager   db = new DbManager())
IT>using (IDataReader rd = db
IT>    .SetCommand(...)
IT>    .ExecuteReader())
IT>{
IT>    User    user    = new User();
IT>    Project project = new Project();

IT>    Map.ToObject(rd, user);
IT>    Map.ToObject(rd, project);
IT>}
IT>

IT>По идее должно работать.
Привет.
Делаю следующие
        [Test]
        [Category(Category.Dvoryadkin)]
        public void MapingManyObject2Test()
        {
            string text1 = @"
select top 10    
    a1.ProjectId as ProjectId, a1.ProjectName as ProjectName, 
    a1.BriefDescription as BriefDescription, a1.ProjectRating as ProjectRating, 
    a1.Description as [Description], a1.CustomerID as CustomerID, 
    a1.CurrentStateTypeId as CurrentStateTypeId
from 
    Project a1";

            Session session = Session.CreateSession();
            using (DbManager db = new DbManager(session.Connection))
            {
                using (IDataReader rd = db.SetCommand(text1).ExecuteReader())
                {

                    ProjectInfo projectInfo = new ProjectInfo();


                    Map.ToObject(rd, projectInfo);
                }
            }
        }

Тест упрастил на поднятие одного объекта, в болдовой строке вылетает exception
class DataReaderSource
метод
object IMapDataSource.GetFieldValue(int i, object entity)
{
return _dataReader.GetValue(i);
}

версия RFD 1.3.0.0

    System.Object    {System.InvalidOperationException}    System.Object
    _className    null    string
    _COMPlusExceptionCode    -532459699    int
    _exceptionMethod    <undefined value>    System.Reflection.MethodBase
    _exceptionMethodString    null    string
    _helpURL    null    string
    _HResult    -2146233079    int
    _innerException    { }    System.Exception
    _message    "Недопустимая попытка чтения при отсутствии данных."    string
    _remoteStackIndex    0    int
    _remoteStackTraceString    null    string
    _source    null    string
    _stackTrace    <undefined value>    System.Object
    _stackTraceString    null    string
    _xcode    -532459699    int
    _xptrs    0    int
    HelpLink    null    string
    HResult    -2146233079    int
    InnerException    { }    System.Exception
    Message    "Недопустимая попытка чтения при отсутствии данных."    string
    Source    null    string
    StackTrace    null    string
    TargetSite    <undefined value>    System.Reflection.MethodBase


СТЕК
    rsdn.framework.data.dll!Rsdn.Framework.Data.Mapping.DataReaderSource.Rsdn.Framework.Data.Mapping.IMapDataSource.GetFieldValue(int i = 0, System.Object entity = {System.Data.SqlClient.SqlDataReader}) Line 43 + 0x16 bytes    C#
     rsdn.framework.data.dll!Rsdn.Framework.Data.Mapping.Map.MapInternal(Rsdn.Framework.Data.Mapping.IMapDataSource source = {Rsdn.Framework.Data.Mapping.DataReaderSource}, System.Object sourceData = {System.Data.SqlClient.SqlDataReader}, Rsdn.Framework.Data.Mapping.IMapDataReceiver receiver = {Mirax.Architex.Core.UnitTests.TestEntity.ProjectInfo.Descriptor}, System.Object receiverData = {Mirax.Architex.Core.UnitTests.TestEntity.ProjectInfo}) Line 164 + 0x16 bytes    C#
     rsdn.framework.data.dll!Rsdn.Framework.Data.Mapping.Map.ToObject(System.Object source = {System.Data.SqlClient.SqlDataReader}, System.Object dest = {Mirax.Architex.Core.UnitTests.TestEntity.ProjectInfo}) Line 240    C#
     mirax.architex.core.unittests.dll!Mirax.Architex.Core.UnitTests.Mapping.MapingManyObject2Test() Line 111 + 0xc bytes    C#
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[3]: Из одной строки поднимать два объекта.
От: QwErTys  
Дата: 06.12.05 06:30
Оценка:
Вопрос отпал.
просто протупил с конструкцией

using (IDataReader rd = db.SetCommand(text1).ExecuteReader())
{
  ProjectInfo projectInfo = new ProjectInfo();
  Map.ToObject(rd, projectInfo);
}
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[4]: Из одной строки поднимать два объекта.
От: QwErTys  
Дата: 06.12.05 07:37
Оценка:
Вот что получилось в результате.
Задача поднять из одного row 2 объекта. Столбцы имеют alias`ы.
По наводке Игоря получилось следующее.

    [Test]
    [Category(Category.Dvoryadkin)]
    public void MapingManyObject2Test()
    {
        string text = @"
select top 10
a0.UserId a0_UserId, a0.Name a0_Name, 
a0.DateCreate a0_DateCreate, a0.LastUpdate a0_LastUpdate, 
a0.FotoImage a0_FotoImage,

a1.ProjectId a1_ProjectId, a1.ProjectName a1_ProjectName, a1.BriefDescription a1_BriefDescription, a1.ProjectRating a1_ProjectRating, a1.Description a1_Description, a1.CustomerID a1_CustomerID, a1.CurrentStateTypeId a1_CurrentStateTypeId
from 
[User] a0, Project a1 ";
        
//            IDbCommand command = _dataBaseProvider.CreateCommandText(text);
        Session session = Session.CreateSession();
        ArrayList list = new ArrayList();

        Hashtable mapUserInfo = new Hashtable();

        mapUserInfo["a0_UserId"] = "UserId";
        mapUserInfo["a0_Name"] = "Name";
        mapUserInfo["a0_DateCreate"] = "DateCreate";
        mapUserInfo["a0_LastUpdate"] = "LastUpdate";
        mapUserInfo["a0_FotoImage"] = "FotoImage";

        Hashtable mapProjectInfo = new Hashtable();

        mapProjectInfo["a1_ProjectId"] = "ProjectId";
        mapProjectInfo["a1_ProjectName"] = "ProjectName";
        mapProjectInfo["a1_BriefDescription"] = "BriefDescription";
        mapProjectInfo["a1_ProjectRating"] = "ProjectRating";
        mapProjectInfo["a1_Description"] = "Description";
        mapProjectInfo["a1_CustomerID"] = "CustomerID";
        mapProjectInfo["a1_CurrentStateTypeId"] = "CurrentStateTypeId";


        using (DbManager db = new DbManager(session.Connection))
        {

            DbManager setCommand = db.SetCommand(text);
            using (IDataReader rd = setCommand.ExecuteReader())
            {
                while (rd.Read()) 
                {
                    ArrayList row = new ArrayList();

                    UserInfo userInfo = new UserInfo();
                    ProjectInfo projectInfo = new ProjectInfo();

                    MyReceiver destUserInfo = new MyReceiver(mapUserInfo, userInfo);
                    Map.ToObject(rd, destUserInfo);
                    MyReceiver destProjectInfo = new MyReceiver(mapProjectInfo, projectInfo);
                    Map.ToObject(rd, destProjectInfo);

                    row.Add(userInfo);
                    row.Add(projectInfo);
                
                    list.Add(row);
                }
            }
        }
        Assert.IsNotNull(list);
        Console.Out.WriteLine("list.Count = {0}", list.Count);
        Assert.AreEqual(10, list.Count);
    }


public class MyReceiver : IMapDataReceiver
{
    public MyReceiver(Hashtable hash, object entity)
    {
        _receiver = Map.Descriptor(entity.GetType());
        _hash     = hash;
        _entity   = entity;
    }

    IMapDataReceiver _receiver;
    Hashtable        _hash;
    object           _entity;

    public int GetOrdinal (string name)
    {
        object mapName = _hash[name];

        if (mapName == null) name = String.Empty;
        else name = mapName.ToString();

        return _receiver.GetOrdinal(name);
    }

    public void SetFieldValue(int i, string name, object entity, object value)
    {
        object mapName = _hash[name];

        if (mapName == null)
            name = mapName.ToString();

        _receiver.SetFieldValue(i, name, _entity, value);
    }
}
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[5]: Из одной строки поднимать два объекта.
От: QwErTys  
Дата: 06.12.05 08:40
Оценка:
QET>>>Тоесть, альясы меняются динамически, что нужно сделать c RFD что бы ему в рантайме прописывать связи?
IT>>Это уже сложнее. Можно поизвращаться с IMapDataReceiver.
IT>Можно ещё сам объект наследовать от этого интерфейса, тогда не надо будет создавать промежуточный.
Наследовать не охота . Вопрос, когда наследовать нет желания в runtime генеряться сборки и кладутся в файловую
систему, можно как то это избежать? Или сделать так что бы место сохранения можно было настроить.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[6]: Из одной строки поднимать два объекта.
От: SiAVoL Россия  
Дата: 06.12.05 08:59
Оценка: 3 (1)
Здравствуйте, QwErTys, Вы писали:

QET>Вопрос, когда наследовать нет желания в runtime генеряться сборки и кладутся в файловую

QET>систему, можно как то это избежать? Или сделать так что бы место сохранения можно было настроить.
скомпилировать RFD без директивы DEBUG. Вроде бы она даже в релизной конфигурации стоит, надо ее убрать.
... << RSDN@Home 1.2.0 alpha rev. 569>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.