简体   繁体   English

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

[英]NHibernate.Linq, WCF RIA Services, weird error

I have a Silverlight Business Application project set up, with these codes. 我使用这些代码设置了Silverlight业务应用程序项目。

I have this domain class: 我有这个域类:

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; }
}

The domain objects mapping has been set up and working fine. 域对象映射已设置并正常工作。

The I have this DTO class: 我有这个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 is used to flatten the object and make sure no unnecessary relations from being serialized and transfered over the wire. DTO用于展平对象,并确保没有不必要的关系被序列化和通过电线传输。

Then I have this RIA DomainService (there are several variations of the GetSectors() method, I'll explain later): 然后我有了这个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 is just a parent class that provides handling for NHibernate session. BaseDomainService只是一个为NHibernate会话提供处理的父类。 I set the session to live per web request. 我将会话设置为每个Web请求生存。

Then I hook up the service to a DataGrid (Silverlight Toolkit) in a XAML page: 然后我将服务连接到XAML页面中的DataGrid(Silverlight Toolkit):

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

When calling the various methods, I got these results: 在调用各种方法时,我得到了以下结果:

  1. Method GetSectors1() produce an exception "Load operation failed for query 'GetSectors1'. Unable to cast object of type NHibernate.Linq.Expressions.EntityExpression' to type 'NHibernate.Linq.Expressions.CollectionAccessExpression'." 方法GetSectors1()产生一个异常“加载操作失败,查询'GetSectors1'。无法将类型为NHibernate.Linq.Expressions.EntityExpression的对象强制转换为'NHibernate.Linq.Expressions.CollectionAccessExpression'。” .

    This is the best way that I'm trying to achive. 这是我想要实现的最佳方式。 I want to use the AutoMapper library to automatically map the domain class to the DTO. 我想使用AutoMapper库自动将域类映射到DTO。 I'm quite positive that the problem is not from the AutoMapper since I also get the error if I call a method from inside the anonymous method passed into Select, eg. 我非常肯定这个问题不是来自AutoMapper,因为如果我从传入Select的匿名方法中调用一个方法,我也会得到错误,例如。 GetSession().Linq<Sector>().Select(x => CustomMap(x)) . GetSession().Linq<Sector>().Select(x => CustomMap(x))

  2. Method GetSectors2() displays the data correctly in the grid, but this defeats the purpose of using IQueryable, the call would not be lazy evaluated. 方法GetSectors2()在网格中正确显示数据,但这违背了使用IQueryable的目的,调用不会延迟评估。

  3. Method GetSectors3() fetches the data, but only the Id and CreatedOn which is in the parent class BaseDomain. 方法GetSectors3()获取数据,但仅获取父类BaseDomain中的Id和CreatedOn。 The Code and Name are both null. 代码和名称均为空。

  4. Method GetSectors4() fetches the data correctly and lazily evaluated, but I don't want to manually map my domain to DTO every time like this! 方法GetSectors4()正确地获取数据并进行懒惰评估,但我不想每次都像我这样手动将我的域映射到DTO!

So what gives? 什么给出了什么? The results are so far away than what I expected! 结果远远超出我的预期! Any idea on how to make this work? 有关如何使这项工作的任何想法? Any advice? 有什么建议?

I appreciate any help, I'm nearly lost. 我很感激任何帮助,我几乎迷失了。 Thank you very much. 非常感谢你。

GetSession().Linq() .ToList() .Select(x => CustomMap(x)) GetSession ()。Linq()。 ToList ()。 Select (x => CustomMap(x))

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

Well, one thing you can do to make things easier is separate the select expression: 好吧,你可以做的一件事就是让选择表达式分开:

For instance: 例如:

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

And then use it as: 然后将其用作:

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

You can define that method inside the Dto. 您可以在Dto中定义该方法。 Btw, it's mostly called presentation model when using it inside RIA services, just for search purposes:). 顺便说一句,在RIA服务中使用它时,它主要被称为表示模型,仅用于搜索目的:)。 I haven't tried this yet (i found your question when searching for same answers as you do, but your question got me thinking) but i don't see why it wouldn't work. 我还没有尝试过这个问题(我在搜索与你相同的答案时找到了你的问题,但你的问题让我思考)但我不明白为什么它不起作用。 Plus i'm using plenty of code generation in the process, so i just generate this part. 另外我在这个过程中使用了大量代码,所以我只生成这个部分。 Hope this helps! 希望这可以帮助!

The reason you are getting these exceptions when using custom methods inside select statements before calling .ToList() is because there is no way for NHibernate to convert those methods into SQL. 在调用.ToList()之前在select语句中使用自定义方法时获得这些异常的原因是因为NHibernate无法将这些方法转换为SQL。

Nhibernate tries to convert your LINQ statement with your select into SQL when you call .ToList(). 当您调用.ToList()时,Nhibernate会尝试使用select into转换LINQ语句。 It can't convert your automapper code into SQL (which is in the select statment). 它无法将您的automapper代码转换为SQL(在select语句中)。 That is why you have to select the object from the database first then call .ToList() to execute the SQL and then go over the list again and map it. 这就是为什么你必须首先从数据库中选择对象,然后调用.ToList()来执行SQL,然后再次遍历列表并映射它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM