1

,我有以下數據模型LazyLoad在NHibernate和ASP.NET的Web API服務

public class Profile : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual int Sequence { get; set; } 
    public virtual string Description { get; set; } 
    public virtual IList<MapService> MapServices { get; set; } 
} 

public class MapService : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual string Url { get; set; } 
    public virtual int MaximumResolution { get; set; } 
} 

正如你所看到的,一個輪廓有很多地圖服務(S)。

而且這種關係是多方面的。

我正在構建返回配置文件數據的ASP.NET Web API rest服務。 我有兩個電話,一個返回所有配置文件,第二個由ID過濾,用下面的網址

http://myapp/api/profiles 
http://myapp/api/profiles/:id 

我使用NHibernate在API控制數據訪問。

在Web API控制器看起來像這樣

public class ProfilesController : ApiController 
{ 
    public ProfilesController() 
    { 
    } 

    public IEnumerator<Profile> GetAllProfiles() 
    { 
     using (Session = .. create nhibernate session) 
     { 
      return Session.Query<Profile>().GetEnumerator(); 
     } 
    } 
} 

當我返回整個列表,我不想讓地圖服務(S),只是名稱和ID

這樣的細節,我以爲我會做懶加載。 所以,我配置了使用功能NHibernate如下

public class ProfileMapping : ClassMap<Profile> 
{ 
    public ProfileMapping() 
    { 
     Table("PROFILE"); 
     Id(x => x.Id, "OBJECT_ID"); 
     Map(x => x.Name, "PROFILE_NAME"); 
     Map(x => x.Sequence, "SEQUENCE_NO"); 
     Map(x => x.Description, "DESCR"); 
     HasManyToMany<MapService>(x => x.MapServices).LazyLoad(). 
      Table("PROFILE_MAP_SERVICE").ParentKeyColumn("PROFILE_ID").ChildKeyColumn("MAP_SERVICE_ID"); 
    } 
} 

我想通過這樣NHibernate的映射,我將只返回輪廓數據,而無需的地圖服務列表

的細節,但是當我打電話休息服務返回整個數據這樣

http://myapp/api/profiles 

我得到這個錯誤

「消息」:「發生錯誤」,」 「ExceptionMessage」:「'ObjectContent`1'類型未能序列化內容類型的響應主體'application/json

」Message「:」發生錯誤。「,」ExceptionMessage「:」Initializing [Domain.Profile #2] - 無法懶惰地初始化一個角色集合:Domain.Profile.MapServices,沒有會話或會話被關閉「,」ExceptionType「:」NHibernate.LazyInitializationException「,」StackTrace「:」

看來, nhibernate正在返回沒有mapservices的配置文件列表,並關閉會話。

但他們以某種方式Web API服務試圖在序列化過程中訪問地圖服務列表。

如何告訴web api服務忽略地圖服務列表?

回答

5

這裏的簡單的方法是引入DTO對象:

public class ProfileDto 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual string Sequence { get; set; } // or Guid... 
    public virtual string Description { get; set; } 
    ... // if more needed 
} 

然後調整API控制器方法

public IEnumerable<ProfileDto> GetAllProfiles() 
{ 
    using (var session = ...) 
    { 
     return session.Query<Profile>() 
      .Select(entity => new ProfileDto 
      { 
       Id = entity.ID, 
       Name = entity.Name, 
       Sequence = entity.Sequence, 
       Description = entity.Description, 
      }) 
      .ToList(); 
    } 
} 

最重要的是這裏所述呼叫.ToList()這將確保DB服務器的所有負載均在會話生存期(使用條款)期間完成。 Automapper可能是下一步,使它更容易(少代碼)...

+0

謝謝 似乎沒有辦法沒有這個dto –

+0

偉大的,如果這有幫助 –