NHibernate.Linq,WCF RIA服务,奇怪的错误

时间:2010-02-26 04:11:40

标签: silverlight linq nhibernate wcf-ria-services

我已经使用这些代码设置了Silverlight业务应用程序项目。

我有这个域类:

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会话提供处理的父类。我将会话设置为按网络请求生效。

然后我将服务连接到XAML页面中的DataGrid(Silverlight Toolkit):

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!

  5. 那是什么给出的?结果远远超出我的预期!有关如何使这项工作的任何想法?有什么建议?

    我感谢任何帮助,我几乎迷失了。非常感谢你。

3 个答案:

答案 0 :(得分:0)

GetSession()。Linq() .ToList() .Select(x =&gt; CustomMap(x))

另见http://www.mail-archive.com/nhusers@googlegroups.com/msg12003.html

答案 1 :(得分: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服务中使用它时,它主要被称为表示模型,仅用于搜索目的:)。我还没有尝试过这个问题(我在搜索相同的答案时发现了你的问题,但你的问题让我思考)但我不明白为什么它不起作用。另外我在这个过程中使用了大量代码,所以我只生成这个部分。希望这有帮助!

答案 2 :(得分:0)

在调用.ToList()之前在select语句中使用自定义方法时获得这些异常的原因是因为NHibernate无法将这些方法转换为SQL。

当您调用.ToList()时,Nhibernate尝试使用select into SQL转换LINQ语句。它无法将您的automapper代码转换为SQL(在select语句中)。这就是为什么你必须首先从数据库中选择对象,然后调用.ToList()来执行SQL,然后再次遍历列表并映射它。