2010-02-26 1 views
3

У меня есть проект приложения Silverlight Business Application с этими кодами.NHibernate.Linq, WCF RIA Services, weird error

У меня есть этот класс домена:

public class BaseDomain 
{ 
    public virtual Guid Id { get; set; } 
    public virtual DateTime CreatedOn { get; set; } 
} 

public class Sector : BaseDomain 
{ 
    public virtual string Code { get; set; } 
    public virtual string Name { get; set; } 
} 

домен объекты отображение было создано и работает нормально.

У меня есть этот DTO класс:

public class SectorDto : BaseDto 
{ 
    [Key] 
    public virtual Guid Id { get; set; } 
    public virtual DateTime CreatedOn { get; set; } 
    public virtual string Code { get; set; } 
    public virtual string Name { get; set; } 

    public SectorDto() 
    { 
    } 

    public SectorDto(Sector d) 
    { 
     Id = d.Id; 
     CreatedOn = d.CreatedOn; 
     Code = d.Code; 
     Name = d.Name; 
    } 
} 

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

Тогда у меня есть эта RIA DomainService (есть несколько вариантов на GetSectors() метода, я объясню позже):

[EnableClientAccess] 
public class OrganizationService : BaseDomainService 
{ 
    public IQueryable<SectorDto> GetSectors1() 
    { 
     return GetSession().Linq<Sector>() 
       .Select(x => Mapper.Map<Sector, SectorDto>(x)); 
    } 

    public IQueryable<SectorDto> GetSectors2() 
    { 
     return GetSession().Linq<Sector>().ToList() 
       .Select(x => new SectorDto(x)).AsQueryable(); 
    } 

    public IQueryable<SectorDto> GetSectors3() 
    { 
     return GetSession().Linq<Sector>().Select(x => new SectorDto(x)); 
    } 

    public IQueryable<SectorDto> GetSectors4() 
    { 
     return GetSession().Linq<Sector>().Select(x => new SectorDto() { 
      Id = x.Id, CreatedOn = x.CreatedOn, Name = x.Name, Code = x.Code }); 
    } 
} 

BaseDomainService только что обеспечивает обработку для NHibernate сессии родительского класса. Я установил сеанс для каждого веб-запроса.

Тогда я подключить услугу к DataGrid (Silverlight Toolkit) в страницу XAML:

var ctx = new App.Web.Services.OrganizationContext(); 
SectorGrid.ItemsSource = ctx.SectorDtos; 
ctx.Load(s.GetSectors1Query()); 

При вызове различных методов, я получил эти результаты:

  1. Метод GetSectors1() производят исключение «Ошибка загрузки для запроса« GetSectors1 ». Невозможно передать объект типа NHibernate.Linq.Expressions.EntityExpression 'для ввода« NHibernate.Linq.Expressions.CollectionAccessExpression »«..

    Это лучший способ, который я пытаюсь достичь. Я хочу использовать библиотеку AutoMapper, чтобы автоматически сопоставить класс домена с DTO. Я вполне уверен, что проблема не в AutoMapper, так как я также получаю ошибку, если я вызываю метод из анонимного метода, переданного в Select, например. GetSession().Linq<Sector>().Select(x => CustomMap(x)).

  2. Метод GetSectors2() отображают данные правильно в сетке, но это поражение цели с помощью IQueryable, вызов не будет ленивым оценено.

  3. Метод GetSectors3() извлекает данные, но только Id и CreatedOn, которые находятся в родительском классе BaseDomain. Код и имя являются нулевыми.

  4. Метод GetSectors4() извлекает данные правильно и лениво оценивается, но я не хочу вручную сопоставлять свой домен с DTO каждый раз, как это!

Так что же дает? Результаты настолько далеки, что я ожидал! Любая идея о том, как сделать эту работу? Любой совет?

Я ценю любую помощь, я почти потерян. Большое спасибо.

+0

Вы пытались использовать HQL или API-интерфейс Criteria вместо Linq? Так ли это работает? –

+1

Мне нужен LINQ, чтобы получить результат как IQueryable, так что RIA Service DomainDataSource может автоматически обрабатывать пейджинг, фильтрацию, сортировку и т. Д. – Ikhwan

+0

Пробовал ли провайдер Linq в магистрали NHibernate (по сравнению с провайдером NHContrib Linq, который вы используете Теперь)? –

ответ

0

Ну, одна вещь, которую вы можете сделать, чтобы сделать вещи проще отдельно избранных выражение:

Например:

public Expression<Func<Sector,SectorDto>> EntityToDto = 
     x => new SectorDto 
      { 
       Id = d.Id; 
       CreatedOn = d.CreatedOn; 
       Code = d.Code; 
       Name = d.Name; 
      }; 

И затем использовать его как:

public IQueryable<SectorDto> GetSectors4() 
    { 
     return GetSession().Linq<Sector>().Select(EntityToDto); 
    } 

Вы можете определить, что метамфетамин внутри Dto. Кстати, в основном это называется презентационной моделью при ее использовании внутри служб RIA, только для целей поиска :). Я еще не пробовал это (я нашел ваш вопрос при поиске тех же ответов, что и вы, но ваш вопрос заставил меня задуматься), но я не понимаю, почему это не сработает. Плюс я использую много генерации кода в этом процессе, поэтому я просто создаю эту часть. Надеюсь это поможет!

0

Причина, по которой вы получаете эти исключения при использовании пользовательских методов внутри операторов select перед вызовом .ToList() - это потому, что NHibernate не может преобразовать эти методы в SQL.

Nhibernate пытается преобразовать ваш оператор LINQ с вашим выбором в SQL при вызове .ToList(). Он не может преобразовать ваш код automapper в SQL (который находится в выбранном статусе). Вот почему вам нужно сначала выбрать объект из базы данных, а затем вызвать .ToList() для выполнения SQL, а затем перебрать список и отобразить его.