- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑这个人为的域:
namespace TryHibernate.Example {
public class Computer
{
public int Id { get; set; }
public IList<Device> Devices { get; set; }
}
public class Device
{
public int Id { get; set; }
public Maker Maker { get; set; }
}
public class Maker
{
public int Id { get; set; }
public string Name { get; set; }
}
} // namespace
如果我只查询所有计算机,它们的设备将随机排序。我想让他们按制造商的名字订购。我真的不能用 HasMany().OrderBy()
来做,因为据我所知,OrderBy
只能使用本地列(所以我可以按 Device.Id
,例如)。此外,在每个查询的基础上控制排序会很好,所以我正在寻找 QueryOver
解决方案。
我能到达的最远的地方是:
using (ISessionFactory sessionFactory = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.UsingFile("temp.sqlite").ShowSql())
.Mappings(m => m.AutoMappings.Add(
AutoMap.AssemblyOf<Computer>(new ExampleConfig())
.Conventions.Add(DefaultLazy.Never())
.Conventions.Add(DefaultCascade.All())))
.ExposeConfiguration(c => new SchemaExport(c).Create(true, true))
.BuildSessionFactory())
{
using (ISession db = sessionFactory.OpenSession())
{
Computer comp = new Computer();
comp.Devices = new List<Device>();
Device dev1 = new Device();
comp.Devices.Add(dev1);
dev1.Maker = new Maker() { Name = "IBM"};
Device dev2 = new Device();
comp.Devices.Add(dev2);
dev2.Maker = new Maker() { Name = "Acer"};
db.Persist(comp);
db.Flush();
}
using (ISession db = sessionFactory.OpenSession())
{ // This is the part I'm having trouble with:
Device devAlias = null;
Maker makerAlias = null;
IList<Computer> comps = db.QueryOver<Computer>()
.JoinAlias(c => c.Devices, () => devAlias)
.JoinAlias(() => devAlias.Maker, () => makerAlias)
.OrderBy(() => makerAlias.Name).Asc
.List();
Console.WriteLine(comps.Count);
foreach (Device dev in comps[0].Devices)
{
Console.WriteLine(dev.Maker.Name);
}
}
}
当然,它并没有按照我的意愿行事。它尝试按制造商的名称对整个列表进行排序。它也成功了,正如我从 SQL 中看到的那样,我实际上得到了一个无用的计算机笛卡尔积,其设备由设备制造商分类。
但随后它发出另一个 SQL 查询来获取设备,这次没有排序。我想 NHibernate 不知道我的连接是为了获取 child 。
问题是,我如何控制第二个查询?例如,按制造商的名称订购设备,或者让每个 Computer.Devices
列表只包含由 IBM 制造的设备(如果有的话)。我想我需要一个子查询,但我应该在哪里插入它呢?
为了完整起见,这是我的配置:
class ExampleConfig : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type.Namespace == "TryHibernate.Example";
}
}
最佳答案
您可以通过干扰 Device
es 检索的 SQL 选择语句来实现此目的。对我来说最优雅的解决方案是使用自定义加载器。但这是
not supported through Fluent NHibernate .幸运的是,您可以在项目的某处编写单个 hbm.xml,然后像这样通过 fluent 添加它:
设备.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
<class name="TryHibernate.Example.Device, TryHibernate" table="Device">
<id name="Id" type="System.Int32, mscorlib" column="Id" generator="identity" />
<property name="Name" />
<many-to-one name="Maker" column="MakerId" />
<many-to-one name="Computer" column="ComputerId" />
<loader query-ref="DeviceLoader" />
</class>
<sql-query name="DeviceLoader">
<return alias="dev" class="TryHibernate.Example.Device, TryHibernate" lock-mode="read">
<return-property name="Computer" column="ComputerId" />
<return-property name="Maker" column="MakerId" />
</return>
SELECT Device.Id AS {dev.Id}, Device.Name As {dev.Name}, Device.MakerId AS {dev.MakerId}, Device.ComputerId AS {dev.ComputerId}
FROM Device INNER JOIN Maker ON Maker.Id = Device.MakerId
WHERE Device.Id=?
ORDER BY Device.ComputerId, Maker.Name
</sql-query>
</hibernate-mapping>
然后在构建 session 工厂时做:
using (ISessionFactory sessionFactory = Fluently.Configure() .Database(SQLiteConfiguration.Standard.UsingFile("temp.sqlite").ShowSql()) .Mappings(m => m.AutoMappings.Add( AutoMap.AssemblyOf(new ExampleConfig()) .Conventions.Add(DefaultLazy.Never()) .Conventions.Add(DefaultCascade.All()))) .Mappings(m => m.HbmMappings.AddFromAssembly(Assembly.GetExecutingAssembly())) .ExposeConfiguration(c => new SchemaExport(c).Create(true, true)) .BuildSessionFactory())
Another thought that hit me is you could specify Subselect()
for your mapping; like this:
public class DeviceMap : ClassMap<Device>
{
public DeviceMap()
{
Table("Device");
Subselect(@"
SELECT TOP 100 Device.Id , Device.Name, Device.MakerId , Device.ComputerId
FROM Device INNER JOIN Maker ON Maker.Id = Device.MakerId
ORDER BY Device.ComputerId, Maker.Name
");
Id(x => x.Id);
Map(x => x.Name);
References(x => x.Computer).Column("ComputerId");
References(x => x.Maker).Column("MakerId");
}
如您所见,我使用了 TOP
子句。这是必要的,因为 sub-select 语句变成了一个子查询,你可能知道
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
还有一个方法是实现一个IInterceptor
接口(interface)并适本地改变SQL。像这样:
public class SqlStatementInterceptor : EmptyInterceptor
{
public override SqlString OnPrepareStatement(SqlString sql)
{
var result = sql;
if (sql.IndexOfCaseInsensitive("FROM Device") != -1)
{
var sqlText = string.Format("WITH cteDev AS ({0}{1}{0}){0}SELECT cteDev.* FROM cteDev INNER JOIN Maker ON cteDev.MakerId1_0_ = Maker.Id ORDER BY Maker.Name", Environment.NewLine, sql.ToString());
result = sql
.Insert(0, "WITH cteDev AS (")
.Append(")SELECT cteDev.* FROM cteDev INNER JOIN Maker ON cteDev.MakerId1_0_ = Maker.Id ORDER BY Maker.Name");
;
}
Trace.WriteLine(result.ToString());
return result;
}
}
*** 对于这个,您需要使用约定并了解 NHibernate 如何生成表和列的名称。
关于NHibernate QueryOver 对每个一对多集合进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38414904/
我一直在为初学者阅读 nhibernate 3.0 并阅读了一些常见错误(我犯了一些错误) 我想知道将一个或多个记录设为只读有哪些策略。现在我取回所有行并循环遍历它们,使它们通过 session.Re
我们有一个使用 NHibernate 的相当健壮的系统,我们正在从单个数据库服务器迁移到拥有两台服务器,一台用于管理,另一台用于我们面向公众的网站。这主要是为了让我们可以使用不会影响当前站点的工作流来
我在尝试构建一个时遇到以下错误 session 工厂: PersistenceTests.Can_Map_Orders_To_Database : Failed System.IndexOutOfRa
如果客户有很多订单附加到他们。您将如何使用 NHibernate 延迟加载订单列表。 是不是需要设置映射文件?任何帮助或示例都会很棒。 最佳答案 Chris 的建议是我会怎么做,但是如果您想在运行时执
我正在尝试使用 HQL 对一个简单的查询进行分页,并将总行数作为同一查询的一部分进行检索。 我的查询很简单... var members = UnitOfWork.CurrentSession.Cre
我有旧版数据库,存储的日期表示无日期为9999-21-31, 列Till_Date的类型为DateTime not-null="true"。 在应用程序中,我要构建持久化类,将no-date表示为nu
您可以指定命名空间和程序集以使用 HBM 文件顶部的类型: 您可以在同一个映射文件中使用来自多个程序集/命名空间的类型,如果可以,这样做的语法是什么? 最佳答案 您可以从 HBM 文件的顶部删除默认
如何强制 NHibernate 在多对多集合上执行 RIGHT 外连接或 INNER 连接而不是 LEFT 外连接? 我想这样做的原因是因为过滤应用于集合元素。使用左连接,您将获得与未过滤查询相同的返
我们开始在我的工作场所使用NHibernate,包括从映射生成模式。我们的DBA想要的一件事是主键和外键关系的名称一致。我已经能够设置FK约束名称,但是在的文档中看,它似乎不存在命名主键约束的方法。
我需要NHibernate来执行这样的查询: SELECT * FROM Users ORDER BY Func(FirstName, LastName) Standart NHibernate Or
假设在一个实体中有属性 id、用户名、年龄、地址。现在我只想要 id 和 username 并使用此代码。 投影可以从查询中返回实体列表以外的内容。 var proj = Projections.Pr
我花了很长时间,但我终于让 nHibernate 的 Hello World 工作了。在我做了“延迟加载”之后它起作用了。老实说,我无法告诉您为什么这一切都有效,但确实如此,现在我正在阅读您不需要延迟
假设您有两个类,Person 和 Address。 Person 有一个对 Address 的引用,如下所示: public class Person { public virtual Addre
我在 NHibernate 引用文档 中阅读第 10 章“只读实体”如下: http://nhibernate.info/doc/nh/en/index.html#readonly 但不幸的是我不知道
有谁知道 NHibernate 是否支持从存储过程返回输出参数?我在文档中进行了搜索,但无法真正找到任何可以确认的内容。 最佳答案 我面临同样的问题。 NHibernate 不允许您以这种方式使用存储
简而言之,什么工作得更快: SessionFactory 预编译 XML 配置,或 流畅的NHibernate提供 以编程方式配置? 最佳答案 我个人的经验是,Configuration 对象的构建(
我的域类具有如下所示的集合: private List _foos = new List(); public virtual ReadOnlyCollection Foos { get { retur
当我有一个带有一对多子集合的实体对象时,我需要查询一个特定的子对象,是否有我还没有想出的功能或一些巧妙的模式来避免 NHibernate获取整个子集合? 例子: class Parent {
在我的域中,员工和部门具有一对多的双向关系;为了让子员工同步这个,我有一个“内部”访问字段,用于部门中员工的集合(NHibernate 的 Iesi),否则它将是只读公共(public)的。像这样:
我有一个 nhibernate 自定义类型,我想用 Fluent NHibernate 映射它。 HBM 映射如下所示。 Services.Data.DateConventionTyp
我是一名优秀的程序员,十分优秀!