我有两个实体A
和B
,其中A
与B
有一对多的关系。我想创建一个NHibernate查询,该查询使用所有A
记录来获取所有B
实体,其中:
A
实体处于活动状态B
实体在日期范围内(我有2个c#
DateTime
对象)。 entity A +----+--------+ | id | active | +----+--------+ | 1 | 1 | | 2 | 0 | | 3 | 1 | +----+--------+ entity B +----+------+-------+------------+ | id | year | month | foreign_id | +----+------+-------+------------+ | 1 | 2000 | 11 | 1 | | 2 | 2001 | 12 | 2 | | 3 | 2002 | 4 | 1 | +----+------+-------+------------+
到目前为止,我已经尝试过:
return this.sessionFactory.GetCurrentSession()
.QueryOver<A>()
.Where(x => x.Active)
.JoinQueryOver(x => x.BList)
.WhereRestrictionOn(y => y.Year * 12 + y.Month) // the problem is here, exception below
.IsBetween(2000 * 12 + 1) // january 2000
.And(2010 * 12 + 3) // march 2010
.List();
System.InvalidOperationException: variable 'x' of type 'Domain.A' referenced from scope '', but it is not defined
通常,我不喜欢以月数为单位计算所有日期的方法(我的应用程序不关心日期,小时数等。)但是,我暂时不希望更改映射(如下所示)。
我希望获得一些帮助来修复这段代码,或者建议我如何做得更好(或最好同时使用)。
更多详细信息:
我的c#
实体看起来像这样:
public class A
{
public virtual int Id { get; set; }
public virtual int Active { get; set; }
public virtual IEnumerable<B> BList { get; set; }
}
public class B
{
public virtual int Month { get; set; }
public virtual int Year { get; set; }
}
internal class AMapping: ClassMap<A>
{
public AMapping()
{
Table("AObjects");
Id(x => x.Id, "id");
Map(x => x.Active, "active");
HasMany(x => x.BList)
.Table("Bobjects")
.KeyColumn("foreign_id")
.Component(y => {
y.Map(b => b.Month, "month");
y.Map(b => b.Year, "year");
});
}
}
答案 0 :(得分:0)
我认为这里的一种方法是使用过滤器。首先要做的是通过过滤器类创建过滤器定义,如下所示:
public class MonthsFilter : FilterDefinition
{
public MonthsFilter()
{
WithName("MonthsFilter")
.AddParameter("startMonths", NHibernateUtil.Int32)
.AddParameter("endMonths", NHibernateUtil.Int32);
}
}
然后,您需要通过ClassMap
方法将过滤器添加到A的BList
中,并添加到ApplyFilter
属性中:
internal class AMapping : ClassMap<A>
{
public AMapping()
{
Table("AObjects");
Id(x => x.Id, "id");
Map(x => x.Active, "active");
HasMany(x => x.BList)
.Table("BObjects")
.KeyColumn("foreign_id")
.Component(y => {
y.Map(b => b.Month, "month");
y.Map(b => b.Year, "year");
}).ApplyFilter<MonthsFilter>("year * 12 + month BETWEEN :startMonths and :endMonths");
}
}
最后,您将需要在发出查询之前启用过滤器,如下所示:
using (var session = sessionFactory.OpenSession())
{
// Enable filter and pass parameters
var startMonthsValue = 2000 * 12 + 1; // january 2000
var endMonthsValue = 2010 * 12 + 3; // march 2010
session.EnableFilter("MonthsFilter")
.SetParameter("startMonths", startMonthsValue)
.SetParameter("endMonths", endMonthsValue);
// Create and execute query (no filter for B needed here)
var list = session.QueryOver<A>()
.Fetch(x => x.BList).Eager // Eager fetch to avoid the N+1 problem due to BList lazy load
.Where(x => x.Active)
.TransformUsing(Transformers.DistinctRootEntity) // List only distinct A entities, to avoid duplicated entries due to eager fetch one-to-many relation
.List();
// Do whatever you want with the results
foreach (var item in list)
{
Console.WriteLine("A id: {0} - B children count: {1}", item.Id, item.BList.Count());
}
}
完整的示例:
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Mapping;
using NHibernate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace NHibernateTests
{
public class A
{
public virtual int Id { get; set; }
public virtual bool Active { get; set; }
public virtual IEnumerable<B> BList { get; set; }
}
public class B
{
public virtual int Month { get; set; }
public virtual int Year { get; set; }
}
internal class AMapping : ClassMap<A>
{
public AMapping()
{
Table("AObjects");
Id(x => x.Id, "id");
Map(x => x.Active, "active");
HasMany(x => x.BList)
.Table("BObjects")
.KeyColumn("foreign_id")
.Component(y => {
y.Map(b => b.Month, "month");
y.Map(b => b.Year, "year");
}).ApplyFilter<MonthsFilter>("year * 12 + month BETWEEN :startMonths and :endMonths");
}
}
public class MonthsFilter : FilterDefinition
{
public MonthsFilter()
{
WithName("MonthsFilter")
.AddParameter("startMonths", NHibernateUtil.Int32)
.AddParameter("endMonths", NHibernateUtil.Int32);
}
}
class Program
{
static void Main(string[] args)
{
var sessionFactory = CreateNHibernateSessionFactory();
using (var session = sessionFactory.OpenSession())
{
// Enable filter and pass parameters
var startMonthsValue = 2000 * 12 + 1; // january 2000
var endMonthsValue = 2010 * 12 + 3; // march 2010
session.EnableFilter("MonthsFilter")
.SetParameter("startMonths", startMonthsValue)
.SetParameter("endMonths", endMonthsValue);
// Create and execute query (no filter needed here)
var list = session.QueryOver<A>()
.Fetch(x => x.BList).Eager // Eager fetch to avoid the N+1 problem due to BList lazy load
.Where(x => x.Active)
.TransformUsing(Transformers.DistinctRootEntity) // List only distinct A entities, to avoid duplicated entries due to eager fetch one-to-many relation
.List();
// Do whatever you want with the results
foreach (var item in list)
{
Console.WriteLine("A id: {0} - B children count: {1}", item.Id, item.BList.Count());
}
}
Console.WriteLine("Press ENTER to continue...");
Console.ReadLine();
}
static ISessionFactory CreateNHibernateSessionFactory()
{
FluentConfiguration fc = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString("Server=.\\SQLEXPRESS;Database=NHibernateTests;Trusted_Connection=True;"))
.Mappings(m => {
m.FluentMappings
.AddFromAssembly(Assembly.GetExecutingAssembly());
});
var config = fc.BuildConfiguration();
return config.SetProperty(NHibernate.Cfg.Environment.ReleaseConnections, "on_close")
.BuildSessionFactory();
}
}
}
有关过滤器的更多信息:
答案 1 :(得分:0)
查询中的主要问题-您无法在function nextNumber() {
if (typeof (Storage) !== "undefined") {
if (localStorage.clickcount) {
localStorage.clickcount = Number(localStorage.clickcount) + 1;
} else {
localStorage.clickcount = 1;
}
Increment = localStorage.clickcount;
} else {
}
}
elem.setAttributeNS(null, "id", "ID " + Increment)//assigning id
中使用计算:
WhereRestrictionOn
此处仅支持映射的属性。
您仍然可以编写所需的查询,但是似乎您必须使用带下划线的.WhereRestrictionOn(y => y.Year * 12 + y.Month) // the problem is here, exception below
帮助方法。像这样:
ICriteria