2012-05-06 53 views
0

我們使用某種標準語言將查詢的where子句從客戶端傳遞到服務器。當涉及到服務器時,我們將它轉​​換爲linq表達式並使用NH執行查詢。 例如「獲得活動頁面」查詢好像是:如何通過linq表達式作爲where子句執行多行更新

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

message.Criteria是實現抽象的標準< T>「原子」準則的組成並擁有和<牛逼粘>和Or < T>準則。每個具體標準實現表達式< 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此更新。
Actualy,我認爲我需要的是用NH linq提供程序將linq表達式解析爲sql。
如何做到這一點?

---------------------------------- Update ----------- ---------------
有鑽入NH內部的一些intermideate結果:

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設置狀態= 2,CloseReason ='多次關閉', 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 as Site31_,
eventextra0_.CreateTimeUTC as CreateTi4_31_,
eventextra0_.Description如Descript5_31_,
eventextra0_.EventTypeDisplayName如EventTyp6_31_,
eventextra0_.Severity如Severity31_,
eventextra0_.Status如 Status31_,
eventextra0_.CreateUser如CreateUser31_,
eventextra0_.Owner如Owner31_,
eventextra0_。 CloseUser爲 CloseUser31_,
eventextra0_.ExceededUTC爲Exceede12_31_,
eventextra0_.ExpiredUTC爲ExpiredUTC31_,
eventextra0_.ClosedUTC爲ClosedUTC31_,
eventextra0_.OwnedUTC as OwnedUTC31_,
eventextra0_。IsFalseEvent爲IsFalse16_31_,
eventextra0_.CloseReason爲CloseRe17_31_,
eventextra0_.IsCloseCommentMandatory爲IsClose18_31_,
eventextra0_.PossibleTrueCloseReasons爲Possibl19_31_,
eventextra0_.PossibleFalseCloseReasons爲Possibl20_31_,
eventextra0_.IsExpired爲IsExpired31_,
eventextra0_.IsExceeded 爲IsExceeded31_,
eventextra0_.SourceElementID爲SourceE23_31_,
eventextra0_.SourceElementDisplayName作爲SourceE24_31_
從 EV_EventData_VW eventextra0_
eventextra0_.IsExpired = 1 and eventextra0_.ExpiredUTC <?

回答

1

您可以使用DML風格的操作,但您必須resort to 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(); 
+0

及其與的幾個milions錶行。在最糟糕的情況下,用戶需要更新所有行。所以我無法獲取事件的ID。是的,我們警告客戶有關問題,但他仍然希望通過選擇標準和單擊來更新多行。 –

+0

@StanB在這種情況下,據我所知,你不能使用LINQ執行DML風格的操作。在工作中我有類似的情況,我很快 - 必須使用StringBuilder建立一個HQL查詢。 – rebelliard

相關問題