如何通过linq表达式将多行更新作为where子句执行

时间:2012-05-06 11:29:52

标签: c# nhibernate

我们使用某种标准语言将查询的where子句从客户端传递给服务器。当涉及到服务器时,我们将其转换为linq表达式并使用NH执行查询。 例如,“获取事件页面”查询似乎是:

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

message.Criteria是实现抽象Criterion&lt; T&gt;的“原子”标准的组合。用&lt; T&gt;粘合。和或者&lt; T&gt;准则。每个具体标准实现表达式&lt; Func&lt; T,bool&gt;&gt; GetExpression()函数。
这是工作。
现在我们想要使用相同的标准来对多行执行更新 我不能只获取符合条件的所有行,然后逐个更新它们。这将是一个性能问题。
我想通过一个命令执行更新:

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

我正在寻找一种用NH实现此更新的方法 Actualy,我认为我需要的是使用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表达式:

  

更新EV_EventData_VW设置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 as   NaturalID31_,
eventextra0_.Site as Site31_,
    eventextra0_.CreateTimeUTC as CreateTi4_31_,
    eventextra0_。描述为Descript5_31_,
    eventextra0_.EventTypeDisplayName as EventTyp6_31_,
    eventextra0_.Severity as Severity31_,
eventextra0_.Status as   Status31_,
eventextra0_ .CreateUser as CreateUser31 _,
    eventextra0_.Owner as Owner31_,
eventextra0_.CloseUser as   CloseUser31_,
eventextra0_ .ExceededUTC as Exceede12_31_,
    eventextra0_.ExpiredUTC as ExpiredUTC31_,
    eventextra0_.ClosedUTC as ClosedUTC31_,
eventextra0_.OwnedUTC   作为OwnedUTC31_,
eventextra0_.IsFalseEvent为IsFalse16_31_,
    eventextra0_.CloseReason为CloseRe17_31_,
    eventextra0_.IsCloseCommentMandatory as IsClose18_31_,
    eventextra0_.PossibleTrueCloseReasons为Possibl19_31_,
    eventextra0_.PossibleFalseCloseReasons为Possibl20_31_,
    eventextra0_.IsExpired as IsExpired31_,
eventextra0_.IsExceeded   as IsExceeded31_,
eventextra0_.SourceElementID as SourceE23_31_,   
eventextra0_.SourceElementDisplayName作为SourceE24_31_
来自   EV_EventData_VW eventextra0_
其中eventextra0_.IsExpired = 1和   eventextra0_.ExpiredUTC&LT ;?

1 个答案:

答案 0 :(得分:1)

您可以使用DML样式操作,但必须resort to HQL

但是,如果您觉得需要使用LINQ进行查询,我会获取相应的ID,这些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();