NHibernate中的LazyLoad和ASP.NET web api服务

Gha*_*han 1 nhibernate lazy-loading fluent-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; }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,配置文件有许多MapService.

这种关系很多很多.

我正在构建一个返回配置文件数据的ASP.NET Web API休息服务.我有两个调用,一个用于返回所有配置文件,第二个用ID过滤,带有以下URL

http://myapp/api/profiles
http://myapp/api/profiles/:id
Run Code Online (Sandbox Code Playgroud)

我在API控制器中使用NHibernate进行数据访问.

Web API控制器看起来像这样

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

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

当我返回整个列表时,我不想要MapService的详细信息,只需要Name和Id

所以,我以为我会做懒加载.所以,我使用流畅的nhibernate配置了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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我想通过这样做,我将只返回没有MapService List细节的配置文件数据

但是当我调用其余服务来返回这样的全部数据时

http://myapp/api/profiles
Run Code Online (Sandbox Code Playgroud)

我收到这个错误

"消息":"发生错误.","ExceptionMessage":"'ObjectContent`1'类型无法序列化内容类型'application/json的响应主体

"消息":"发生错误.","ExceptionMessage":"正在初始化[Domain.Profile#2] - 无法初始化角色集合:Domain.Profile.MapServices,没有会话或会话被关闭"," ExceptionType ":" NHibernate.LazyInitializationException " "堆栈跟踪":"

似乎nhibernate在没有mapservices的情况下返回配置文件列表,并关闭会话.

但他们不知何故web api服务试图在序列化期间访问地图服务列表.

如何告诉web api服务忽略地图服务列表?

Rad*_*ler 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
}
Run Code Online (Sandbox Code Playgroud)

然后调整API Controller方法

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这里最重要的是调用.ToList(),它将确保来自DB服务器的所有负载都在会话生命周期内完成(using子句).自动映像可能是下一步,使其更容易(更少的代码)...