AutoMapper поддерживает Linq?

Я очень интересуюсь Linq к SQL с Ленивой функцией загрузки. И в моем проекте я использовал AutoMapper для отображения Модели DB на Модель предметной области (от DB_RoleInfo кому: DO_RoleInfo). В моем коде репозитория как указано ниже:

    public DO_RoleInfo SelectByKey(Guid Key)
    {
        return SelectAll().Where(x => x.Id == Key).SingleOrDefault();
    }

    public IQueryable<DO_RoleInfo> SelectAll()
    {
        Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
        return from role in _ctx.DB_RoleInfo
               select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
    }

SelectAll метод выполняется хорошо, но когда я звоню SelectByKey, Я получаю ошибку:

Метод “RealMVC.Data. DO_RoleInfo MapDB_RoleInfo, DO_RoleInfo” не мог перевести в SQL.

Случается так, что Автокартопостроитель не поддерживает Linq полностью?

Вместо Автокартопостроителя я попробовал ручной код отображения ниже:

public IQueryable<DO_RoleInfo> SelectAll()
{
    return from role in _ctx.DB_RoleInfo 
    select new DO_RoleInfo 
    {
        Id = role.id,
        name = role.name,
        code = role.code
    };
}

Этот метод прокладывает себе путь, я хочу его к.

22
задан Aaronaught 6 February 2010 в 15:30
поделиться

1 ответ

Измените вторую функцию на это:

public IEnumerable<DO_RoleInfo> SelectAll()
{
    Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
    return from role in _ctx.DB_RoleInfo.ToList()
           select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}

AutoMapper отлично работает с Linq to SQL, но не может быть выполнен как часть отложенного запроса . Добавление ToList () в конце вашего запроса Linq заставляет его немедленно оценивать результаты, вместо того, чтобы пытаться преобразовать сегмент AutoMapper как часть запроса.


Уточнение

Понятие отложенного выполнения ( не «ленивая загрузка») не имеет никакого смысла, если вы изменили результирующий тип на то, что не является данными юридическое лицо.Рассмотрим эти два класса:

public class DB_RoleInfo
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public class DO_RoleInfo
{
    public Role Role { get; set; }    // Enumeration type
}

Теперь рассмотрим следующее сопоставление:

Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>
    .ForMember(dest => dest.Role, opt => opt.MapFrom(src =>
        (Role)Enum.Parse(typeof(Role), src.Name)));

Это сопоставление совершенно нормально (если я не допустил опечатку), но предположим, что вы написали метод SelectAll в своем исходном сообщении вместо мой исправленный:

public IQueryable<DO_RoleInfo> SelectAll()
{
    Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
    return from role in _ctx.DB_RoleInfo
           select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}

Это действительно работает, но, называя себя "запрашиваемым", это ложь. Что произойдет, если я попытаюсь написать против этого:

public IEnumerable<DO_RoleInfo> SelectSome()
{
    return from ri in SelectAll()
           where (ri.Role == Role.Administrator) ||
                 (ri.Role == Role.Executive)
           select ri;
}

Подумайте об этом как следует. Как Linq to SQL , возможно, сможет успешно превратить ваш where в фактический запрос к базе данных?

Linq ничего не знает о классе DO_RoleInfo . Он не знает, как выполнить отображение в обратном направлении - в некоторых случаях это даже невозможно. Конечно, вы можете посмотреть на этот код и ввести «О, это просто, просто найдите« Администратор »или« Исполнительный »в столбце Имя « , но вы » re единственный, кто это знает. Что касается Linq to SQL, запрос - полная чушь.

Представьте, что кто-то дал вам эти инструкции:

Идите в супермаркет и принесите ингредиенты для приготовления индейки Мортона Томпсона.

Если вы не сделали это раньше, а большинство людей этого не сделали, ваш ответ на это указание, скорее всего, будет следующим:

  • Что это, черт возьми?

Вы можете пойти на рынок и вы можете получить определенные ингредиенты по названию, но вы не можете оценить состояние, которое я вам поставил , пока вы там . Сначала мне нужно "отключить отображение" критериев .Я должен вам сказать, вот ингредиенты, которые нам нужны для этого рецепта - теперь идите и принесите их.


Подводя итог, это не простая несовместимость между Linq to SQL и AutoMapper. Он не уникален ни для одной из этих двух библиотек. Не имеет значения , как вы на самом деле выполняете сопоставление с типом, не являющимся сущностью - вы можете так же легко выполнить сопоставление вручную, и вы все равно получите ту же ошибку, потому что теперь вы даете Linq в SQL - набор инструкций, которые больше не понятны, касающиеся загадочных классов, которые не имеют внутреннего сопоставления с каким-либо конкретным типом сущности.

Эта проблема фундаментальна для концепции отображения O / R и отложенного выполнения запроса. проекция - это односторонняя операция . После того, как вы спроектируете, вы больше не сможете вернуться к механизму запросов и сказать о, кстати, вот еще несколько условий для вас . Это очень поздно. Лучшее, что вы можете сделать, - это взять то, что он вам уже дал, и самостоятельно оценить дополнительные условия.


И последнее, но не менее важное: я предлагаю вам обходной путь. Если единственная вещь, которую вы хотите сделать из своего сопоставления, - это фильтр строк, вы можете написать следующее:

public IEnumerable<DO_RoleInfo> SelectRoles(Func<DB_RoleInfo, bool> selector)
{
    Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
    return _ctx.DB_RoleInfo
        .Where(selector)
        .Select(dbr => Mapper.Map<DB_RoleInfo, DO_RoleInfo>(dbr));
}

Это служебный метод, который обрабатывает сопоставление за вас и принимает фильтр на исходном объекте, а не на отображенном объекте. Это может быть полезно, если у вас много разных фильтров, но всегда нужно выполнять одно и то же сопоставление.

Лично я думаю, что вам будет лучше просто правильно написать запросы, сначала определив, что вам нужно получить из базы данных , затем выполнить любые прогнозы / сопоставления, а затем, наконец, если вам необходимо выполнить дополнительную фильтрацию (чего не следует), затем материализовать результаты с помощью ToList () или ToArray () и напишите больше условий в местном списке.

Не пытайтесь использовать AutoMapper или любой другой инструмент, чтобы скрыть реальные сущности, предоставляемые Linq to SQL. Модель предметной области - это ваш открытый интерфейс . Запросы, которые вы пишете, являются аспектом вашей частной реализации . Важно понимать разницу и четко разделять проблемы.

25
ответ дан 29 November 2019 в 03:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: