在我的项目中,我在OrchardProject网站上使用this tutorial在记录之间实现了N对N的关系。我有2个部分:MaterialPart
& CategoryPart
和关联记录。
材料部分
public class MaterialPartRecord : ContentPartRecord {
public MaterialPartRecord() {
Categories = new List<ContentMaterialCategoryRecord>();
}
}
public class MaterialPart : ContentPart<MaterialPartRecord> {
public IEnumerable<CategoryPartRecord> Categories {
get { return Record.Categories.Select(cmcr => cmcr.CategoryPartRecord); }
}
}
CategoryPartRecord
public class CategoryPartRecord : ContentPartRecord {
...
}
public class CategoryPart : ContentPart<CategoryPartRecord> {
...
}
关联记录:
public class ContentMaterialCategoryRecord {
public virtual int Id { get; set; }
public virtual MaterialPartRecord MaterialPartRecord { get; set; }
public virtual CategoryPartRecord CategoryPartRecord { get; set; }
}
现在我需要选择与某个类别相关联的MaterialItems
。到目前为止,我有这种方法来提取它们。它有效,但我不确定这是否正确。
public IEnumerable<MaterialPart> GetMaterialsByCategory(int catId) {
var cs = new CategoriesService(_oServices);
CategoryPartRecord cat = cs.GetItem(catId).Record;
return _oServices.ContentManager
.Query(VersionOptions.Latest, _contentType)
.Join<CommonPartRecord>()
.OrderByDescending(cpr => cpr.PublishedUtc);
.List()
.Where(ci => ci.IsPublished())
.Select(ci => ci.As<MaterialPart>())
.Where(mp => mp.Categories.Contains(cat)); // < ---- ?
}
所以我的问题是:为所需的类别选择materials
的正确方法是什么,这会产生最佳的SQL查询,因为我们只需要inner join
关联的记录表和必需的CategoryPartRecord_Id
字段值。
thaks!
答案 0 :(得分:0)
如果M:N具有配对对象,我们可以使用QueryOver和子查询。最大的好处是,我们收到了一套简单的材料项目,我们可以用它来分页(Take(),Skip())
var session = ... // get curretn session
CategoryPartRecord category = null;
ContentMaterialCategoryRecord pair = null;
MaterialPartRecord material = null;
var subquery = QueryOver.Of<ContentMaterialCategoryRecord>(() => pair)
// now we will join Categories to be able to filter whatever property
.JoinQueryOver(() => pair.CategoryPartRecord, () => category)
// here is the filter
// there could be IN, >= <= ...
.Where(() => category.ID == 1)
// or
.WhereRestrictionOn(c => c.category.ID).IsIn(new[] {1, 2, 3})
...
// now we will return IDs of the Material we are interested in
.Select(x => pair.MaterialPartRecord.Id);
// finally the clean query over the Materials...
var listOfUsers = session.QueryOver<MaterialPartRecord>(() => material )
.WithSubquery
.WhereProperty(() => material.Id)
.In(subquery)
// paging
.Take(10)
.Skip(10)
.List<MaterialPartRecord>();
因此,这将生成最有效的SQL脚本,只有一个子选择,并从材质表中选择干净
注意:即使使用LINQ也可以完成类似的操作。但是QueryOver是我所说的NHibernate最原生的方式。无论如何,principe - 按类别过滤的子查询,以及加载材料的主要查询将保持不变。只有一个SQL Select调用