0

我们使用某种标准语言将查询的 where 子句从客户端传递到服务器。对于服务器,我们将其转换为 linq 表达式并使用 NH 执行查询。例如“获取事件页面”查询看起来像这样:

Session.Query<EventExtractData>()
.Where(message.Criteria.GetExpression())
.OrderByDescending(e => e.CreateTimeUtc)
.Skip(message.Start)
.Take(message.Size)
.ToArray()

message.Criteria 是实现抽象 Criterion<T> 并与 And<T> 和 Or<T> 标准粘合的“原子”标准的组合。每个具体标准都实现了 Expression<Func<T, bool>> GetExpression() 函数。
这是工作。
现在我们想使用相同的标准对多行执行更新。
我不能只获取符合条件的所有行,然后一一更新它们。这将是一个性能问题。
我想通过一个命令执行更新:

UPDATE <real view name of mapped EventExtractData class> 
SET <my business logic> 
WHERE <my criterions' linq expression translated to SQL where clause>

我正在寻找一种使用 NH 实现此更新的方法。
实际上,我认为我需要的是使用 NH linq 提供程序将 linq 表达式解析为 sql。
怎么做?

- - - - - - - - - - - - - - - - - 更新 - - - - - - - - ------------
钻入NH内部有一些中间结果:

var implementor = session.GetSessionImplementation();
var hqlUpdate = "update EventExtractData e set e.Status = 2, e.CloseReason = 'Multiple close', e.ClosedUTC = :now";
var updatePlan = new HQLStringQueryPlan(hqlUpdate, false, implementor.EnabledFilters, implementor.Factory);
string sqlUpdate = updatePlan.SqlStrings[0];

这给了我以下 sql 表达式:

update EV_EventData_VW set Status=2, CloseReason='Multiple close', ClosedUTC=?

现在我将模拟选择查询并得到它的 sql 表达式

var dummyQuery = session.Query<EventExtractData>().Where(message.Criteria.GetExpression());
var nhQuery = new NhLinqExpression(dummyQuery.Expression);
var selectPlan = new HQLExpressionQueryPlan(nhQuery.Key, nhQuery, false, implementor.EnabledFilters, implementor.Factory);
string sqlSelect = selectPlan.SqlStrings[0];

这给了我:

选择
eventextra0_.ID 作为 ID31_,
eventextra0_.NaturalID 作为 NaturalID31_,
eventextra0_.Site 作为 Site31_,
eventextra0_.CreateTimeUTC 作为 CreateTi4_31_,
eventextra0_.Description 作为 Descript5_31_,
eventextra0_.EventTypeDisplayName 作为 EventTyp6_31_,
eventextra0_.Severity 作为 Severity331_,
eventextra0_0_Status 作为
Status .CreateUser 作为 CreateUser31_,
eventextra0_.Owner 作为 Owner31_,
eventextra0_.CloseUser 作为 CloseUser31_,
eventextra0_.ExceededUTC 作为 Exceede12_31_,
eventextra0_.ExpiredUTC 作为 ExpiredUTC31_,
eventextra0_.ClosedUTC 作为 ClosedUTC31_,
eventextra0_.OwnedUTC as OwnedUTC31_,
eventextra0_.IsFalseEvent as IsFalse16_31_,
eventextra0_.CloseReason as CloseRe17_31_,
eventextra0_.IsCloseCommentMandatory as IsClose18_31_,
eventextra0_.PossibleTrueCloseReasons as Possibl19_31_,
eventextra0_.PossibleFalseCloseReasons as Possibl20_31_,
eventextra0_.IsExpired as IsExpired31_,
eventextra0_.IsExceeded as IsExceeded31_,
eventextra0_. SourceElementID 作为 SourceE23_31_,
eventextra0_.SourceElementDisplayName 作为 SourceE24_31_
从 EV_EventData_VW eventextra0_
where eventextra0_.IsExpired=1 and eventextra0_.ExpiredUTC<?

4

1 回答 1

1

您可以使用 DML 风格的操作,但您将不得不求助于 HQL

但是,如果您觉得需要使用 LINQ 进行查询,我会获取相应的 ID,这应该是一个非常轻量级的查询,然后将 HQL 与这些查询一起使用:

var ids = Session.Query<EventExtractData>()
         .Where(message.Criteria.GetExpression())
         .Select(x=>x.Id)
         .ToList();

int count = Session.CreateQuery(@"update EventExtractData evt
                                  set evt.Date =:date 
                                  where evt.Id in (:ids)")
           .SetParameter("date", DateTime.Now)
           .SetParameterList("ids", ids)
           .ExecuteUpdate();
于 2012-05-06T14:55:21.817 回答