NHibernate Insert With SubQuery
本文关键字:SubQuery With Insert NHibernate | 更新日期: 2023-09-27 18:34:02
我有一个表结构:
------------------------------------------------
| id |daily_index|monthly_index| created |
------------------------------------------------
| GUID | 1 | 1 | 10-12-2014 |
| GUID | 2 | 2 | 10-12-2014 |
| GUID | 1 | 3 | 11-12-2014 |
| GUID | 1 | 1 | 01-01-2015 |
------------------------------------------------
我的目标是拥有一个具有灵活自然代码的事务对象,例如
INV-{daily_index}/{month_in_roman}/{year_in_roman}/{monthly_index}
或
INV{ddmmyyyyhhiiss}-{monthly_index}-{daily_index}
或者用户希望的任何内容。
该类将具有一个 Code
属性,该属性将编织这些私有字段,仅用于 UI。
在纯mysql查询中,我会这样做:
INSERT INTO transaction VALUES (// Some GUID, (SELECT COUNT(*) + 1 FROM transaction WHERE DATE(created) = DATE(NOW)), (SELECT COUNT(*) + 1 FROM transaction WHERE MONTH(created) = MONTH(NOW)), NOW());
我的问题是有没有办法在NHibernate中重现这种插入机制?
我考虑了另一种选择,我会使用 COUNT 查询进行 SELECT 查询,但我不知道 NHibernate 是否可以这样做。
另一种选择是制作 MySQL 触发器,但我很想知道这是否可以直接在我的项目中完成。
NHibernate提供了一个覆盖默认插入语句的选项:sql-insert
:
在映射文件中使用此元素,您可以根据自己的喜好更改插入/更新语句,如下所示:
<class name="Student">
<id name="Id" type="Int32">
<generator class="assigned" />
</id>
<property name="Code" length="2000" />
<many-to-one name="Class" column="ClassId" not-null="true"/>
<sql-insert>insert into Student (Code, ClassId, Id) values (UPPER(?), ? , ?)</sql-insert>
</class>
当然,您还必须自定义sql-update
。
但是,确定每列的正确位置很棘手。这是来自NH文档:
您可以通过为 NHibernate.Persister.Entity level.启用此级别后,NHibernate(英语:NHibernate( 将打印出用于创建、更新、删除的静态 SQL 等实体。(要查看预期的顺序,请记住不要包含 映射文件中的自定义 SQL,因为这将覆盖 NHibernate生成的静态sql。
参考:用于创建、更新和删除的自定义 SQL
这是我喜欢的 NHibernate ...即使这里有一个解决方案。我们需要的是:
13.3. DML 样式的操作
小引用:
如前所述,自动和透明的对象/关系映射与对象状态的管理有关。这意味着对象状态在内存中可用,因此直接在数据库中操作(使用 SQL 数据操作语言 (DML( 语句:插入、更新、删除(数据不会影响内存中状态。但是,NHibernate提供了批量SQL样式DML语句执行的方法,这些方法通过Hibernate查询语言(HQL(执行。
关于插入(小提取物(:
INSERT语句的伪语法为:INSERT INTO EntityName properties_list select_statement。需要注意的几点:
- 只有插入...选择。。。支持表单;不是插入...值。。。形式。
- 该properties_list类似于 SQL INSERT 语句中的列选角。对于映射继承中涉及的实体,只能在properties_list中使用在该给定类级别直接定义的属性。不允许使用超类属性;子类属性没有意义。换句话说,INSERT 语句本质上是非多态的。
- 。
来自文档的示例:
ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
var hqlInsert = "insert into DelinquentAccount (id, name) " +
" select c.id, c.name from Customer c where ...";
int createdEntities = s.CreateQuery( hqlInsert )
.ExecuteUpdate();
tx.Commit();
session.Close();
溶液
有了这个,我们可以创建这种选择:
var hqlSelect =
// HQL select clause
" SELECT " +
// guid on the DB side
" UUID(), " +
// this will return matches for today only
" CAST(SUM(CASE WHEN DAY(created)=DAY(CURRENT_TIMESTAMP) THEN 1 ELSE 0 END) as int),"+
// this will return matches for this month - see WHERE
" CAST(Count(*) as int)," +
// the time stamp into created
" CAST(CURRENT_TIMESTAMP as DateTime)" +
// From means - from some entity (the transaction here)
" FROM transaction" +
// Where is here restricting current month
// here we filter just this year and this month records
" WHERE MONTH(created) = MONTH(CURRENT_TIMESTAMP) " +
" AND YEAR(created) = YEAR(CURRENT_TIMESTAMP) ";
这将是完整的插入
var hqlInsert = "INSERT INTO AuditLog (id, daily_index, monthly_index, created ) "
+ hqlSelect; // the above select
这应该符合预期:
ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
var hqlInsert = ... // see code above to create DML HQL
int createdEntities = session
.CreateQuery( hqlInsert )
.ExecuteUpdate();
tx.Commit();
session.Close();