2010-02-26 81 views
3

我有一個Silverlight商業應用程序項目設置,與這些代碼。NHibernate.Linq,WCF RIA服務,奇怪的錯誤

我有這個領域類:測繪已經成立並運作良好

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的會議一個父類。我將會話設置爲按每個Web請求生活。

然後我勾了一個XAML頁面服務到DataGrid(Silverlight工具包):

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()獲取數據,但只獲取父類BaseDomain中的Id和CreatedOn。代碼和名稱都是空的。

  4. 方法GetSectors4()獲取數據和正確評價懶洋洋的,但我不希望我的域名每次都是這樣手動映射到DTO!

那麼是什麼給?結果遠遠超出我的預期!任何想法如何使這項工作?有什麼建議?

我感謝任何幫助,我幾乎失去了。非常感謝你。

+0

您是否嘗試過使用HQL或Criteria API代替Linq?那它有用嗎? –

+1

我需要LINQ來獲得結果作爲IQueryable,以便RIA Service DomainDataSource控件可以自動處理分頁,過濾,排序等。 – Ikhwan

+0

您是否嘗試過NHibernate主幹中的Linq提供程序(與您似乎使用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

在調用.ToList()之前在select語句中使用自定義方法時,您會得到這些異常的原因是因爲NHibernate沒有辦法將這些方法轉換爲SQL。

當您調用.ToList()時,Nhibernate會嘗試將您的LINQ語句與選擇轉換爲SQL。它不能將自動映射程序代碼轉換爲SQL(這是選擇語句)。這就是爲什麼你必須首先從數據庫中選擇對象,然後調用.ToList()來執行SQL,然後再次遍歷列表並映射它。