Преобразование сущности в DTO вместе с дочерними сущностями - PullRequest
0 голосов
/ 29 ноября 2018

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

Вот код, который я использую для преобразования объекта сущности;

IEnumerable<SystemArea> result = (from sa in CurrentContext.systemarea                                 
                                 select new SystemArea
                                 {
                                     SystemAreaId = sa.SystemAreaId,
                                     SystemAreaCode = sa.SystemAreaCode,
                                     SystemAreaType = sa.SystemAreaType,
                                     SystemAreaDescription = sa.SystemAreaDescription,
                                     SystemAreaCreatedDate = sa.SystemAreaCreatedDate,
                                     SystemAreaUpdateDate = sa.SystemAreaUpdateDate,
                                     SystemAreaStatus = sa.SystemAreaStatus,
                                     Count = sa.systemareafunctionality.Count,
                                     SystemAreaFunctionality = sa.systemareafunctionality.Select(e => new SystemAreaFunctionality { SystemAreaCode =e.SystemAreaCode })
                                 }).ToList();

Здесь переменная count должна подтвердить, есть ли в нем дочерние данные.

SystemAreaFunctionality - это дочерний объект, который я пытаюсь преобразовать здесь с помощью функции SELECT , но это всегда пустая коллекция.Остальные данные присваиваются родительскому объекту, но здесь не хватает только записей дочерней таблицы.Где я иду не так, пожалуйста, помогите!

Сгенерированный SQL:

SELECT
`Project3`.`C1`, 
`Project3`.`SystemAreaId`, 
`Project3`.`SystemAreaCode`, 
`Project3`.`SystemAreaType`, 
`Project3`.`SystemAreaDescription`, 
`Project3`.`SystemAreaCreatedDate`, 
`Project3`.`SystemAreaUpdateDate`, 
`Project3`.`SystemAreaStatus`, 
`Project3`.`C3` AS `C2`, 
`Project3`.`C2` AS `C3`, 
`Project3`.`SystemAreaCode1`
FROM (SELECT
`Project1`.`SystemAreaId`, 
`Project1`.`SystemAreaCode`, 
`Project1`.`SystemAreaType`, 
`Project1`.`SystemAreaDescription`, 
`Project1`.`SystemAreaCreatedDate`, 
`Project1`.`SystemAreaUpdateDate`, 
`Project1`.`SystemAreaStatus`, 
1 AS `C1`, 
`Project2`.`SystemAreaCode` AS `SystemAreaCode1`, 
`Project2`.`C1` AS `C2`, 
`Project1`.`C1` AS `C3`
FROM (SELECT
`Extent1`.`SystemAreaId`, 
`Extent1`.`SystemAreaCode`, 
`Extent1`.`SystemAreaType`, 
`Extent1`.`SystemAreaDescription`, 
`Extent1`.`SystemAreaCreatedDate`, 
`Extent1`.`SystemAreaUpdateDate`, 
`Extent1`.`SystemAreaStatus`, 
(SELECT
COUNT(1) AS `A1`
FROM `systemareafunctionality` AS `Extent2`
 WHERE `Extent1`.`SystemAreaCode` = `Extent2`.`SystemAreaCode`) AS `C1`
FROM `systemarea` AS `Extent1`) AS `Project1` LEFT OUTER JOIN (SELECT
`Extent3`.`SystemAreaCode`, 
1 AS `C1`
FROM `systemareafunctionality` AS `Extent3`) AS `Project2` ON `Project1`.`SystemAreaCode` = `Project2`.`SystemAreaCode`) AS `Project3`
 ORDER BY 
`Project3`.`SystemAreaCode` ASC, 
`Project3`.`C2` ASC

Вывод JSON:

[{"SystemAreaId": 1, "SystemAreaCode": "KIO", "SystemAreaType": "KIOSK", "SystemAreaDescription": "задачи, связанные с регистратором", "SystemAreaCreatedDate": "/ Date (1543421018000) /", "SystemAreaUpdateDate": "/ Date (1543421018000) /","SystemAreaStatus": true, "SystemAreaFunctionality": [], "Count": 1}]

PS: Пожалуйста, не предлагайте методы автоматического расширения или расширения.Спасибо!

Ответы [ 4 ]

0 голосов
/ 08 декабря 2018

Включение должно помочь вам, вот так:

    IEnumerable<SystemArea> result = (from sa in CurrentContext.systemarea.Include("systemareafunctionality")                                 
                             select new SystemArea
                             {
                                 SystemAreaId = sa.SystemAreaId,
                                 SystemAreaCode = sa.SystemAreaCode,
                                 SystemAreaType = sa.SystemAreaType,
                                 SystemAreaDescription = sa.SystemAreaDescription,
                                 SystemAreaCreatedDate = sa.SystemAreaCreatedDate,
                                 SystemAreaUpdateDate = sa.SystemAreaUpdateDate,
                                 SystemAreaStatus = sa.SystemAreaStatus,
                                 Count = sa.systemareafunctionality.Count,
                                 SystemAreaFunctionality = sa.systemareafunctionality.Select(e => new SystemAreaFunctionality { SystemAreaCode =e.SystemAreaCode })
                             }).ToList();
0 голосов
/ 29 ноября 2018

Очевидно, что CurrentContext - это Dbcontext с хотя бы таблицей SystemAreas и таблицей SystemAreaFunctionalities.

Кажется, что каждый SystemArea имеет ноль или более SystemAreaFunctionalities;каждый SystemAreaFunctionality принадлежит ровно одному SystemArea, прямому отношению один-ко-многим с использованием внешнего ключа.

Примечание: может случиться так, что у вас есть отношение ко многим, ответ будетбыть похожим

Увы, вы забыли написать свои классы, поэтому я сделаю снимок:

class SystemArea
{
    public int Id {get; set;}
    ... // other properties

    // every SystemArea has zero or more SystemAreaFunctionalities (one-to-many)
    public virtual ICollection<SystemAreaFunctionality> SystemAreaFunctionalities {get; set;}
}

class SystemAreaFunctionality
{
    public int Id {get; set;}
    ... // other properties

    // every SystemAreaFunctionality belongs to exactly one SystemArea, using foreign key
    public int SystemAreaId {get; set;}
    public virtual SystemArea SystemArea {get; set;}
}

В структуре сущностей столбцы ваших таблиц представлены не виртуальнымисвойства, виртуальные свойства представляют отношения между таблицами.(один ко многим, много ко многим, ...)

для полноты:

class CurrentContext : DbContext
{
    public DbSet<SystemArea> SystemAreas {get; set;}
    public DbSet<SystemAreaFunctionality> SystemAreaFunctionalities {get; set;}
}

Если людям нужны элементы со своими подпунктами, например Schools с их Students, Customers с их Orders и т. Д. Люди склонны выполнять (group)Join.Однако при использовании сущностных каркасов соединения редко необходимы.Вместо этого используйте ICollections.Платформа сущностей знает отношения и знает, какую (группу) объединить для выполнения.

Регулярно я вижу, что люди используют Include, но если вы сделаете это, вы выберете полный объект, что не очень эффективно.Предположим, у вас есть SystemArea с Id = 10 и 1000 SystemAreaFunctionalities, вы знаете, что каждый SystemAreaFunctionality имеет внешний ключ SystemAreaId со значением 10. Вместо того, чтобы отправлять это значение только один раз в качестве первичного ключа SystemArea, Include также выберет все 1000 внешних ключей с этим значением 10. Какая трата вычислительной мощности!

При запросе данных всегда используйте Select и выбирайте только те свойства, которые вы фактически планируете использовать,Используйте «Включить», только если вы планируете обновить включенный объект.

Вы писали:

SystemAreaFunctionality - это дочерний объект, который я пытаюсь преобразовать здесь ...

Не понятно, чего вы действительно хотите.Вы хотите получить коллекцию всех используемых SystemAreaCodes?Или вы действительно хотите коллекцию новых SystemAreaFunctionalities, где заполнено только одно поле: SystemAreaCode?Из-за того, что вы используете единственное имя свойства, кажется, вы не хотите коллекцию, а только один элемент.

var result = currentContext.SystemAreas.Select(systemArea => new
{
     Id = systemArea.Id,
     Code = systemArea.Code,
     ...

     // if you want a collection of SystemAreaFunctionalities
     // where every SystemAreaFunctionality is filled with only SysemAreaCode
     // do the following:
     SystemAreaFunctionalities = systemArea.SystemAreaFunctionalities
          .Select(systemAreaFunctionality => new SystemAreFunctionality
          {
               SystemAreaCode = systemAreaFunctionality.SystemAreaCode,
          })
          .ToList(),   // DON'T FORGET THIS, OR YOU WON'T GET RESULTS!
    })
    .ToList()
}

Я думаю, что причина ваших пустых SystemAreaFunctionalities заключается в том, что вы забыли сделать ToList().

Поскольку вы использовали ToList (), у вас автоматически будет счетчик выбранных функций SystemAreaFunctionalities.Нет необходимости выбирать этот счетчик отдельно.

Одна из более медленных частей запросов к базе данных - это передача выбранных данных из системы управления базами данных в локальный процесс.Рекомендуется выбирать только те данные, которые вы действительно планируете использовать

Ваш запрос не очень эффективен, поскольку вы выбираете полные SystemAreaFunctionalities и заполняете только SystemAreaCode.Все остальные поля будут заполнены значениями по умолчанию.Помимо более медленного запроса, у ваших абонентов также создается впечатление, что они правильно заполнены SystemAreaFunctionalities.Улучшенная версия будет выглядеть так:

var result = currentContext.SystemAreas.Select(systemArea => new
{
     // select only the properties you actually plan to use
     Id = systemArea.Id,
     Code = systemArea.Code,
     ...


     // if you only need the SystemAreaCodes, select only that property
     SystemAreaCodes = systemArea.SystemAreaFunctionalities
          .Select(systemAreaFunctionality => systemAreaFunctionality.SystemAreaCode)
          .ToList(),
    })
    .ToList()
};

Конечно, если вам нужно больше, чем просто SystemAreaCodes, но несколько SystemAreaFunctionalities, выберите их:

...
SystemAreaFunctionalities = systemArea.SystemAreaFunctionalities
    .Select(systemAreaFunctionality => new
    {
        // again: select only the properties you plan to use!
        Id = systemAreaFunctionality.Id
        SystemAreaCode = systemAreaFunctionality.SystemAreaCode,
     })
0 голосов
/ 08 декабря 2018

МНЕНИЕ:

Мне потребовалось два дня, чтобы заставить MySQL (последнюю версию) работать с EF, и поверьте мне, это было кропотливо, и наоборот, EF с MSSQL настолько прост и легкореализовать.

Одна вещь, с которой я столкнулся, это то, что Oracle не заинтересован в предоставлении поддержки бесплатной версии MySQL, поэтому они небрежно относятся к документации новой версии и предоставляют нестабильные коннекторы .NET.

АКТУАЛЬНЫЙ ОТВЕТ:

EF вел себя так странно, что он загружал данные только в дочернюю сущность (SystemAreaFunctionality) только в том случае, если я попросил EF загрузить дочернюю частьдочерняя сущность (то есть SystemAreaFunctionalityEmployeeRoleMapping, которая является дочерней по отношению к SystemAreaFuncionality), что также означает, что мне пришлось получить ненужные данные.

Поэтому мой запрос ссылки выглядит следующим образом:

var result = (from sa in CurrentContext.systemarea
                          select new SystemArea
                          {
                              SystemAreaId = sa.SystemAreaId,
                              SystemAreaType = sa.SystemAreaType,
                              Count = sa.systemareafunctionality.Count,
                              SystemAreaFunctionalities = sa.systemareafunctionality.Select(saf => new SystemAreaFunctionality
                              {
                                  SystemAreaId = saf.SystemAreaId,
                                  SystemAreaFunctionalityController = saf.SystemAreaFunctionalityController,
                                  SystemAreaFunctionalityAction = saf.SystemAreaFunctionalityAction,
                                  SystemAreaFunctionalityType = saf.SystemAreaFunctionalityType,
                                  SystemAreaFunctionalityEmployeeRoleMappings = saf.systemareafunctionalityemployeerolemapping.Select(saferm => new SystemAreaFunctionalityEmployeeRoleMapping
                                  {
                                      SystemAreaFunctionalityEmployeeRoleMappingId = saferm.SystemAreaFunctionalityEmployeeRoleMappingId,
                                      SystemAreaFunctionalityCreatedDate = saferm.SystemAreaFunctionalityCreatedDate
                                  })
                              })
                          }).ToList();

ALTERNATIVELY:

Попытка использовать тот же запрос linq (опубликованный в OP) с другой базой данных на этот раз с PostgreSQL плюс разъем npgsql и на удивление EF дает мне именно то, что я хочу без дополнительного багажа.Кроме того, PostgreSQL дает лучшую производительность с EF, чем MySQL.Поэтому я предполагаю, что переключение на PostgreSQL было бы лучшим вариантом.

PS: Если вы выбираете СУБД с открытыми исходными кодами, пожалуйста, ознакомьтесь с этим перед переходомв MySQL:

0 голосов
/ 29 ноября 2018

Используйте это:

CurrentContext.systemarea.Include('systemareafunctionality')

или

IEnumerable<SystemArea> result = (from sa in CurrentContext.systemarea    
                             join systemareafunctionality in CurrentContext.systemareafunctionality on sa.systemareafunctionalityID equals systemareafunctionality.ID
                             select new SystemArea
                             {
                                 SystemAreaId = sa.SystemAreaId,
                                 SystemAreaCode = sa.SystemAreaCode,
                                 SystemAreaType = sa.SystemAreaType,
                                 SystemAreaDescription = sa.SystemAreaDescription,
                                 SystemAreaCreatedDate = sa.SystemAreaCreatedDate,
                                 SystemAreaUpdateDate = sa.SystemAreaUpdateDate,
                                 SystemAreaStatus = SystemAreaStatus,
                                 Count = systemareafunctionality.Count,
                                 SystemAreaFunctionality = systemareafunctionality.Select(e => new SystemAreaFunctionality { SystemAreaCode =e.SystemAreaCode })
                             }).ToList();

или

IEnumerable<SystemArea> result = (from sa in CurrentContext.systemarea    
                         join systemareafunctionality in CurrentContext.systemareafunctionality on sa.systemareafunctionalityID equals systemareafunctionality.ID into item1 from subitem1 in item1.DefaultIfEmpty() 
                         select new SystemArea
                         {
                             SystemAreaId = sa.SystemAreaId,
                             SystemAreaCode = sa.SystemAreaCode,
                             SystemAreaType = sa.SystemAreaType,
                             SystemAreaDescription = sa.SystemAreaDescription,
                             SystemAreaCreatedDate = sa.SystemAreaCreatedDate,
                             SystemAreaUpdateDate = sa.SystemAreaUpdateDate,
                             SystemAreaStatus = SystemAreaStatus,
                             Count = systemareafunctionality.Count,
                             SystemAreaFunctionality = systemareafunctionality.Select(e => new SystemAreaFunctionality { SystemAreaCode =e.SystemAreaCode })
                         }).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...