我已经使用这些代码设置了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());
在调用各种方法时,我得到了这些结果:
方法 GetSectors1()产生异常“查询加载操作失败'GetSectors1'。无法将类型为NHibernate.Linq.Expressions.EntityExpression的对象强制转换为' NHibernate.Linq.Expressions.CollectionAccessExpression”。“。
这是我努力实现的最佳方式。我想使用AutoMapper库自动将域类映射到DTO。我非常肯定这个问题不是来自AutoMapper,因为如果我从传入Select的匿名方法中调用一个方法,我也会得到错误,例如。 GetSession().Linq<Sector>().Select(x => CustomMap(x))
。
方法 GetSectors2()在网格中正确显示数据,但这违背了使用IQueryable的目的,调用不会延迟评估。
方法 GetSectors3()获取数据,但仅获取父类BaseDomain中的Id和CreatedOn。代码和名称均为空。
方法 GetSectors4()正确获取数据并进行延迟评估,但我不想每次都像我这样手动将域名映射到DTO!
那是什么给出的?结果远远超出我的预期!有关如何使这项工作的任何想法?有什么建议?
我感谢任何帮助,我几乎迷失了。非常感谢你。
答案 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,然后再次遍历列表并映射它。