在尝试了很多东西之后,我仍然无法找到使用Fluent NHibernate查询以下关系的正确方法。 如果我不得不编写SQL查询,那么这将是一个更容易的任务。希望得到一些更好的建议,以避免N + 1问题和未经优化的自动生成的SQL查询。
我有以下关系,如下所示:
标签可以包含与之相关的媒体内容(各种预定义大小的图像,视频,文档等)
- 1个标签可以映射多个媒体项目(让我们说尺寸为32x32,64x64,600x100,0或更多视频的图像)
- 每个媒体项目都映射到媒体描述,这有助于识别媒体的大小和类型
- 相同的媒体项可以由不同的标签使用。例如,所有标签都没有任何图标的通用图像。
实体:
媒体
public class Media:IEntity
{
private ICollection<TagMedia> _tagMedia;
public virtual int Id { get; set; }
public virtual string FilePath { get; set; }
public virtual MediaType MediaType { get; set; }
public virtual ICollection<TagMedia> TagMedia
{
get { return _tagMedia?? (_tagMedia= new List<TagMedia>()); }
protected set { _tagMedia= value; }
}
}
标签
public class Tag:IEntity
{
private ICollection<TagMedia> _tagMedia;
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<TagMedia> TagMedia
{
get { return _tagMedia?? (_tagMedia= new List<TagMedia>()); }
set { _tagMedia= value; }
}
}
TagMedia
public class TagMedia :IEntity
{
public virtual int Id { get; set; }
public virtual Media Media { get; set; }
public virtual Tag Tag { get; set; }
public virtual DateTime AddedOn { get; set; }
}
MediaType
public class MediaType:IEntity
{
public virtual int Id { get; set; }
public virtual string Description { get; set; }
}
映射
MediaMapping
public class MediaMapping : IAutoMappingOverride<Media>
{
public void Override(AutoMapping<Media> mapping)
{
mapping.Map(c => c.FileName).CustomSqlType("varchar(60)").Not.Nullable();
}
}
TagMapping
public class TagMapping : IAutoMappingOverride<Tag>
{
public void Override(AutoMapping<Tag> mapping)
{
mapping.HasMany<TagMedia>(c => c.TagMedia)
.KeyColumn("TagId")
.Cascade.SaveUpdate()
.BatchSize(25);
mapping.BatchSize(25);
mapping.DynamicUpdate();
mapping.DynamicInsert();
}
}
TagMediaMapping
public class TagMediaMapping : IAutoMappingOverride<TagMedia>
{
public void Override(AutoMapping<TagMedia> mapping)
{
mapping.Map(c=>c.AddedOn);
}
}
查询:
以下查询获取映射到标记的所有媒体的笛卡尔积,并且不会消除&#34; Icon-16x16&#34;以外的记录。我希望ORM返回不超过一行。
任何帮助都将受到高度赞赏。
_session.Query<Tag>()
.FetchMany(x => x.TagMedia)
.ThenFetch(x => x.Media)
.ThenFetch(x=>x.MediaType)
.Where(c => c.Id == id
&& c.TaxonomyMedia.Any(x=>x.Media.MediaType.Description== "Icon-16x16"))
.SingleOrDefault();
生成的SQL:
exec sp_executesql N'select *
from [Tag] Tag0_ left outer join [TagMedia] Tagme1_ on Tag0_.TagId=Tagme1_.TagId
left outer join [Media] media2_ on Tagme1_.MediaId=media2_.MediaId
left outer join [MediaType] mediatype3_ on media2_.MediaTypeId=mediatype3_.MediaTypeId
where Tag0_.TagId=@p0
and (exists (select Tagme4_.TagMediaId
from [TagMedia] Tagme4_ inner join [Media] media5_ on Tagme4_.MediaId=media5_.MediaId inner join [MediaType] mediatype6_ on media5_.MediaTypeId=mediatype6_.MediaTypeId where Tag0_.TagId=Tagme4_.TagId and mediatype6_.MediaTypeDescription=@p1))',N'@p0 int,@p1 nvarchar(4000)',@p0=102,@p1=N'Icon-16x16'
go
答案 0 :(得分:0)
SingleOrDefault函数是一个LINQ函数,NHibernate没有实现。使用。取(1) 我认为解决方案是:
_session.Query<Tag>()
.FetchMany(x => x.TagMedia)
.ThenFetch(x => x.Media)
.ThenFetch(x=>x.MediaType)
.Where(c => c.Id == id
&& c.TaxonomyMedia.Any(x=>x.Media.MediaType.Description== "Icon-16x16"))
.Take(1)
.SingleOrDefault();