Cod*_*che 3 collections nhibernate-criteria nhibernate-projections
我正在使用NH Criteria检索实体并将选择性字段投影到自定义类(有点像将数据投影到ViewModel上以便在MVC视图上显示).
使用ProjectionList很容易:
var emailCriteria = mSession.CreateCriteria<Email>();
emailCriteria.SetProjection(
Projections.ProjectionList()
.Add(Projections.Property("Subject"), "Subject")
);
emailCriteria.SetResultTransformer(Transformers.AliasToBean<EmailDataModel>());
var result = emailCriteria.List<EmailDataModel>();
Run Code Online (Sandbox Code Playgroud)
但是,我的实体包含一个集合,我也希望将它带回来,并将其作为集合投影到我的自定义类中.
我的域模型看起来(简化形式)如下:
public class Email {
public string Subject
public List<EmailAttachment> Attachments
etc...
}
public class EmailAttachment {
public UploadedFile File
}
public class UploadedFile {
public string Filename
public UploadedFileData Data
}
public class UploadedFileData {
public byte[] Data
}
Run Code Online (Sandbox Code Playgroud)
这是我要投影到的"数据模型"类:
public class EmailDataModel {
public string Subject
public List<EmailAttachmentDataModel> Attachments
}
public class EmailAttachmentDataModel {
public string Filename
public byte[] Data
}
Run Code Online (Sandbox Code Playgroud)
现在我知道这些模型看起来非常相似,你会想到"有什么意义?",但那是因为我简化了它们.很高兴能够将我的域对象压缩成方便的数据模型.
我的一个大问题是如何从我的子对象(在本例中为UploadedFile.Filename和UploadedFileData.Data)深入访问必要的字段,并将它们作为EmailAttachmentDataModel集合投影到我的EmailDataModel上.
我在网上阅读了很多关于访问子集合的文章 - 使用EmailCriteria.CreateAlias或EmailCriteria.CreateQuery - 但我没有找到任何解释如何将子集合作为集合进行投影的内容.
我希望对于有兴趣修改NH Criteria查询的人来说,这将是一个有用的练习.
好吧,我想我已经解决了这个升级到NHibernate 3并使用QueryOver的问题.这是我的代码现在的样子:
//Declare entities
Email email = null;
EmailAttachment attachment = null;
UploadedFile file = null;
Byte[] fileData = null;
//Select data from parent and child objects
var results = mSession.QueryOver<QueuedEmail>(() => email)
.JoinAlias(() => email.Attachments, () => attachment, JoinType.LeftOuterJoin)
.JoinAlias(() => attachment.File, () => file, JoinType.LeftOuterJoin)
.JoinAlias(() => file.Data, () => fileData, JoinType.LeftOuterJoin)
.TransformUsing(Transformers.DistinctRootEntity)
.List<Email>()
//Loop through results projecting fields onto POCO
.Select(x => new EmailDataModel()
{
Id = x.Id,
Body = x.Body,
AttachmentCount = x.Attachments.Count(),
FromAddress = x.FromAddress,
//Loop through child collection projecting fields onto POCO
Attachments = x.Attachments.Select(attach => new EmailAttachmentDataModel()
{
Data = attach.File.Data.Data,
Filename = attach.File.Filename,
Id = attach.Id
}).ToArray() //NB Now projecting this collection as an array, not a list
}).ToArray();
Run Code Online (Sandbox Code Playgroud)
就是这样.我们的结果是一个扁平的类,它包含我们需要的数据,以及一组附件(每个附件只包含我们数据结构中的两个字段 - 很好地展平).
你为什么要这样做?
它通过扁平化到我真正想要的字段来简化结果.
我的数据现在被安全地封装在一个可以传递的类中,而不用担心意外更新我的数据(如果你只是传回NH数据实体就可能发生这种情况).
最后(也是最重要的),因为上面的代码只生成一个SELECT语句.如果我坚持使用我原来的Criteria查询,它会为每一行生成一个SELECT,并为链中的下一个孩子生成更多.如果你处理的是小数字,那就没问题了,但如果你可能会返回数千行(就像我在这个例子中那样 - 它是电子邮件引擎的web服务).
我希望这对任何希望进一步深入NHibernate查询的人都有用.就个人而言,我很高兴我现在可以继续我的生活!
| 归档时间: |
|
| 查看次数: |
2155 次 |
| 最近记录: |