Reconcile behaves unexpectedly when conflicts are present in a geometric network.
上次发布: August 25, 2014No Product Found
漏洞 ID 编号
NIM003841
已提交
August 18, 2006
上次修改时间
April 2, 2025
适用范围
No Product Found
找到的版本
9.1
状态
Will Not Be Addressed
开发团队已考虑过该问题或请求,并决定不会解决该问题。 问题的“其他信息”部分可能包含进一步说明。
附加信息
No Public Explanation
解决办法
The user modifed the FilterConflicts developer sample as a workaround. The new coded they added is:'arcdata 060816' pCurrentRow.Store If TypeOf pCurrentRow Is INetworkFeature Then Dim pFeat As IFeature Dim pNetFeat As INetworkFeature Dim pGNC As IGeometricNetworkConnectivity2 Set pNetFeat = pCurrentRow Set pFeat = pCurrentRow Set pGNC = pNetFeat.GeometricNetwork pNetFeat.Disconnect pCurrentRow.Store pGNC.RebuildConnectivity2 pFeat.Shape.Envelope Else pCurrentRow.Store End If'arcdata 060816Here is all the code, the majority of which comes from <a href="http://edn.esri.com/index.cfm?fa=codeExch.sampleDetail&pg=/arcobjects/9.1/Samples/Geodatabase/Versioning/Filter_Conflicts/Filter_Conflicts.htm" target="_blank">http://edn.esri.com/index.cfm?fa=codeExch.sampleDetail&pg=/arcobjects/9.1/Samples/Geodatabase/Versioning/Filter_Conflicts/Filter_Conflicts.htm</a>:VERSION 1.0 CLASSBEGIN MultiUse = -1 'True Persistable = 0 'NotPersistable DataBindingBehavior = 0 'vbNone DataSourceBehavior = 0 'vbNone MTSTransactionMode = 0 'NotAnMTSObjectENDAttribute VB_Name = "WorkspaceExt"Attribute VB_GlobalNameSpace = FalseAttribute VB_Creatable = TrueAttribute VB_PredeclaredId = FalseAttribute VB_Exposed = True' Copyright 1995-2005 ESRI' All rights reserved under the copyright laws of the United States.' You may freely redistribute and use this sample code, with or without modification.' Disclaimer: THE SAMPLE CODE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED' WARRANTIES, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS' FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESRI OR' CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,' OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF' SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS' INTERRUPTION) SUSTAINED BY YOU OR A THIRD PARTY, HOWEVER CAUSED AND ON ANY' THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ARISING IN ANY' WAY OUT OF THE USE OF THIS SAMPLE CODE, EVEN IF ADVISED OF THE POSSIBILITY OF' SUCH DAMAGE.' For additional information contact: Environmental Systems Research Institute, Inc.' Attn: Contracts Dept.' 380 New York Street' Redlands, California, U.S.A. 92373' Email: <a href="mailto:contracts@esri.com" target="_blank">contracts@esri.com</a>'*******************************************************************************' FilterConflicts.WorkspaceExt'' Requirements: This class must be registered with the component category' "ESRI Geodatabase Workspace Extensions".'' Purpose: Responds to OnReconcile and filters out Update/Update conflicts' on Attribute fields where the update to the 2 versions of the' row were on different attribute columns. It leaves the row as' a conflict if the same attribute was changed in both versions.' If the two rows are different on different attribute columns,' the code copies over the new attributes from the prereconcile' version to the current edit version.''*******************************************************************************Option Explicit'To be a valid WorkspaceExtension, you must implement these two interfacesImplements IWorkspaceExtensionImplements IWorkspaceExtensionControl'Since this is a WorkspaceExtension, we do not want to listen to IVersionEvents'because that would create a circular reference. with the VersionedWorkspace.'Instead, the VersionedWorkspace will call the IVersionEvents on every'WorkspaceExtension that implements 'IVersionEventsImplements IVersionEvents'Has a weak-reference to the Workspace. Don't ever maintain a reference to'the Workspace itself or else you will have a circular reference.Private m_pWorkspaceHelper As IWorkspaceHelper'Reference to the current application. This may be "nothing" if the workspace'is opened outside of ArcMap/ArcCatalogPrivate m_pApp As AppRef'This method will be calledPrivate Sub IVersionEvents_OnConflictsDetected(conflictsRemoved As Boolean, errorOccurred As Boolean, errorString As String) On Error GoTo ErrorHandler conflictsRemoved = False errorOccurred = False errorString = "" 'If we have a reference to ArcMap/ArcCatalog, display a message If Not m_pApp Is Nothing Then m_pApp.StatusBar.Message(0) = "Filtering conflicts." End If 'Filter the conflicts conflictsRemoved = FilterConflicts(m_pWorkspaceHelper.Workspace) conflictsRemoved = False 'Required to work around CQ00204310- should be fixed by 9.0 final Exit SubErrorHandler: conflictsRemoved = False errorOccurred = True errorString = "FilterConflicts.OnConflictsDetected: " & Err.DescriptionEnd SubPrivate Sub IVersionEvents_OnReconcile(ByVal VersionName As String, ByVal foundConflicts As Boolean)End Sub'Since we are actually implementing the interface IVersionEvents instead of'listening to events, we need to declare all the methods, even if we aren't'going to use them.Private Sub IVersionEvents_OnRedefineVersion(ByVal oldVersionName As String, ByVal newVersionName As String) MsgBox "redefine " & oldVersionName & " to " & newVersionNameEnd Sub'Since we are actually implementing the interface IVersionEvents instead of'listening to events, we need to declare all the methods, even if we aren't'going to use them.Private Sub IVersionEvents_OnRefreshVersion()End SubPrivate Sub IWorkspaceEdit_StartEditing(ByVal withUndoRedo As Boolean)End Sub'This is where you can specify what tables are DataDictionaryTables and'not shown through ArcCatalog or the GxDialog.Private Property Get IWorkspaceExtension_DataDictionaryTableNames() As esriSystem.IEnumBSTREnd Property'Pass back the ProgID or CLSID of this class in a UID objectPrivate Property Get IWorkspaceExtension_GUID() As esriSystem.IUID Dim pUID As UID Set pUID = New UID pUID.Value = "FilterConflicts.WorkspaceExt" Set IWorkspaceExtension_GUID = pUID Set pUID = NothingEnd Property'Return the name of this Workspace extensionPrivate Property Get IWorkspaceExtension_Name() As String IWorkspaceExtension_Name = "Filter Conflicts Extension"End PropertyPrivate Property Get IWorkspaceExtension_PrivateDatasetNames(ByVal dtype As esriGeoDatabase.esriDatasetType) As esriSystem.IEnumBSTREnd Property'Called when the Workspace first openedPrivate Sub IWorkspaceExtensionControl_Init(ByVal pWorkspaceHelper As esriGeoDatabase.IWorkspaceHelper) 'Save a reference to the WorkspaceHelper, not the Workspace itself Set m_pWorkspaceHelper = pWorkspaceHelper ' Get a reference to ArcMap/ArcCatalog possible. Not necessary. On Error Resume Next Set m_pApp = New AppRefEnd Sub'Free resourcesPrivate Sub IWorkspaceExtensionControl_Shutdown() Set m_pWorkspaceHelper = Nothing Set m_pApp = NothingEnd Sub'Highest level method. Loops through all ConflictClasses calling'FilterConflictClass on each one to filter out all false conflictsPrivate Function FilterConflicts(ByVal pVersionEdit As IVersionEdit) As Boolean Dim pDataset As IDataset Dim sTableName As String Dim pCurrentVersion As IFeatureWorkspace 'What current version after reconcile Dim pPreReconcileVersion As IFeatureWorkspace 'The current version before reconcile Dim pReconcileVersion As IFeatureWorkspace 'The version reconciled against Dim pCommonVersion As IFeatureWorkspace 'The common ancestor version Dim pEnumConflictClass As IEnumConflictClass 'Iterator over all ConflictClasses Dim pConflictClass As IConflictClass FilterConflicts = False 'Get references to the Versions that are used to do the 'comparisons to determine whether or not a field should 'really cause a conflict Set pCurrentVersion = pVersionEdit Set pPreReconcileVersion = pVersionEdit.PreReconcileVersion Set pReconcileVersion = pVersionEdit.ReconcileVersion Set pCommonVersion = pVersionEdit.CommonAncestorVersion 'Loop through all the ConflictClasses, and filter out the 'false conflicts from each ConflictClass. Set pEnumConflictClass = pVersionEdit.ConflictClasses pEnumConflictClass.Reset Set pConflictClass = pEnumConflictClass.Next Do Until pConflictClass Is Nothing Set pDataset = pConflictClass sTableName = <a href="http://pDataset.Name" target="_blank">pDataset.Name</a> If FilterConflictClass(pConflictClass, _ pCurrentVersion.OpenTable(sTableName), _ pPreReconcileVersion.OpenTable(sTableName), _ pReconcileVersion.OpenTable(sTableName), _ pCommonVersion.OpenTable(sTableName)) Then FilterConflicts = True End If Set pConflictClass = pEnumConflictClass.Next Loop 'Free resources Set pCurrentVersion = Nothing Set pPreReconcileVersion = Nothing Set pReconcileVersion = Nothing Set pCommonVersion = Nothing Set pEnumConflictClass = Nothing Set pConflictClass = NothingEnd Function'Second highest level method. Loops through all UpdateUpdate conflicts'on the passed in ConflictClass, filtering out false conflicts'Returns True if it was successfulPrivate Function FilterConflictClass(ByVal pConflictClass As IConflictClass, _ ByVal pCurrentTable As ITable, _ ByVal pPreReconcileTable As ITable, _ ByVal pReconcileTable As ITable, _ ByVal pCommonTable As ITable) As Boolean Dim pDataset As IDataset Dim sTableName As String Dim pSelSet As ISelectionSet Dim pEnumIDs As IEnumIDs Dim oid As Long Dim iNumToRemove As Long Dim vOIDs() As Long FilterConflictClass = False 'Get the Tablename for display purposes Set pDataset = pCurrentTable sTableName = <a href="http://pDataset.Name" target="_blank">pDataset.Name</a> 'Get the SelectionSet holding the UpdateUpdate Conflicts Set pSelSet = pConflictClass.UpdateUpdates 'Get the Enumeration of OIDs of the Conflicting features. 'Loop through them calling FilterConflictRow on each oid Set pEnumIDs = pSelSet.IDs pEnumIDs.Reset oid = pEnumIDs.Next Do Until oid = -1 'If we have a reference to ArcMap/ArcCatalog, display a message If Not m_pApp Is Nothing Then m_pApp.StatusBar.Message(0) = "Filtering conflicts. Table = " & sTableName & " ObjectID = " & oid End If 'Try to filter false conflicts in this row. If successful, 'this will return true and the oid will be added to the 'array of oids to remove from the UpdateUpdate conflicts 'SelectionSet. If FilterConflictRow(pCurrentTable.GetRow(oid), _ pPreReconcileTable.GetRow(oid), _ pReconcileTable.GetRow(oid), _ pCommonTable.GetRow(oid)) Then 'Successful. Increment counter and add oid to array, iNumToRemove = iNumToRemove + 1 ReDim Preserve vOIDs(1 To iNumToRemove) vOIDs(iNumToRemove) = oid End If oid = pEnumIDs.Next Loop 'Check to see if and conflicts were filtered conflicts. If so 'Remove them from the UpdateUpdate Conflicts SelectionSet If iNumToRemove > 0 Then Dim iOldCount As Long iOldCount = pSelSet.Count 'Remove Rows whose false conflicts were corrected pSelSet.RemoveList UBound(vOIDs), vOIDs(1) FilterConflictClass = True End If 'Free resources Set pSelSet = Nothing Set pEnumIDs = NothingEnd Function'Third highest level method. Loops through all Fields on a Row'and if the value was changed in either the PreReconcileVersion'or the ReconcileVersion but not both, copy the changed value'into the CurrentVersion's field (if necessary).'Return True if no field was changed in both versions and'the current version of the Row was updated.'Return False if there is a true conflict. The current version'of the Row is not updatedPrivate Function FilterConflictRow(ByVal pCurrentRow As IRow, _ ByVal pPreReconcileRow As IRow, _ ByVal pReconcileRow As IRow, _ ByVal pCommonRow As IRow) As Boolean Dim pFields As IFields Dim pField As IField Dim i As Long Dim vValues() As Variant Dim pCurrentAnnoFeature As IAnnotationFeature Dim pPreReconcileAnnoFeature As IAnnotationFeature Dim pReconcileAnnoFeature As IAnnotationFeature Dim pCommonAnnoFeature As IAnnotationFeature Dim pFeatureClass As IFeatureClass Dim pAnnoClass As IAnnoClass Dim iElementFieldIndex As Long FilterConflictRow = False 'We have to handle Annotation a little different because 'the ELEMENT field is controlled by an interface called 'IAnnotationFeature that is responsible for setting the 'element and the Shape. If it's annotation get the 'proper interface and ElementFieldIndex otherwise -1 If TypeOf pCurrentRow Is IAnnotationFeature Then Set pCurrentAnnoFeature = pCurrentRow Set pPreReconcileAnnoFeature = pPreReconcileRow Set pReconcileAnnoFeature = pReconcileRow Set pCommonAnnoFeature = pCommonRow Set pFeatureClass = pCurrentRow.Table Set pAnnoClass = pFeatureClass.Extension iElementFieldIndex = pAnnoClass.ElementFieldIndex Else iElementFieldIndex = -1 End If 'Get the IFields and also redim a variant array representing 'the Row's fields. Don't initialize the array because it 'only cares about values that aren't missing Set pFields = pCurrentRow.Fields ReDim vValues(0 To pFields.FieldCount - 1) 'Loop through each field, comparing the values of each version For i = 0 To pFields.FieldCount - 1 Set pField = pFields.Field(i) If (i = iElementFieldIndex) Then 'Since it's Annotation, pass in the Element for comparison instead 'of the ELEMENT value itself. Don't respect non-editable 'fields because it has to go through the method 'IAnnotationFeature.Annotation to set the value anyway 'If FALSE (No Conflict) vValues(i) has the new value If QueryIsFieldConflict(pPreReconcileAnnoFeature.Annotation, _ pReconcileAnnoFeature.Annotation, _ pCommonAnnoFeature.Annotation, _ pField, _ False, _ vValues(i)) Then ' Get out of here because the field has a real conflict Exit Function End If Else 'Not Anno. Compare Values respecing non-editable fields 'If FALSE (No Conflict) vValues(i) has the new value If QueryIsFieldConflict(pPreReconcileRow.Value(i), _ pReconcileRow.Value(i), _ pCommonRow.Value(i), _ pField, _ True, _ vValues(i)) Then ' Get out of here because the field has a real conflict Exit Function End If End If Next i 'If here, it's because there are no real conflicts 'Update the Current Row with all values in vValues that were set For i = 0 To pFields.FieldCount - 1 If Not IsEmpty(vValues(i)) Then If (i = iElementFieldIndex) Then 'Update Anno ELEMENT fields differently pCurrentAnnoFeature.Annotation = vValues(i) Else 'Update every other value the same pCurrentRow.Value(i) = vValues(i) End If End If Next i 'Make sure to store the feature and signify that all conflicts were handled'arcdata 060816' pCurrentRow.Store If TypeOf pCurrentRow Is INetworkFeature Then Dim pFeat As IFeature Dim pNetFeat As INetworkFeature Dim pGNC As IGeometricNetworkConnectivity2 Set pNetFeat = pCurrentRow Set pFeat = pCurrentRow Set pGNC = pNetFeat.GeometricNetwork pNetFeat.Disconnect pCurrentRow.Store pGNC.RebuildConnectivity2 pFeat.Shape.Envelope Else pCurrentRow.Store End If'arcdata 060816 FilterConflictRow = True Set pFields = Nothing Set pField = NothingEnd Function'Returns True if there are conflicts within the field that can't be resolved.'Otherwise, returns False and the byref parameter vValueToUse will store'the value to put back in the Current Edit Version of the row.Private Function QueryIsFieldConflict(ByVal vPreReconcileValue As Variant, _ ByVal vReconcileValue As Variant, _ ByVal vCommonValue As Variant, _ ByVal pField As IField, _ ByVal bCheckIfEditable As Boolean, _ ByRef vValueToUse As Variant) As Boolean On Error GoTo ErrorHandler: QueryIsFieldConflict = False 'Assume there is no conflict If IsEqual(vPreReconcileValue, vReconcileValue) Then 'There's no difference. This means there's no conflict in this field Else 'There's a difference. Check both against common ancestor. 'It's only a conflict if both versions are different than the Common version If IsEqual(vCommonValue, vReconcileValue) Xor _ IsEqual(vCommonValue, vPreReconcileValue) Then 'The field has been updated in one version but not the other. 'Still not a conflict. If IsEqual(vReconcileValue, vCommonValue) Then 'The Pre-reconcile version was updated, update the current version If (Not bCheckIfEditable) Or pField.Editable Then 'This is a byref variant value returned as an in/out parameter vValueToUse = vPreReconcileValue ElseIf (UCase(<a href="http://pField.Name" target="_blank">pField.Name</a>) <> "SHAPE.AREA") And _ (UCase(<a href="http://pField.Name" target="_blank">pField.Name</a>) <> "SHAPE.LEN") Then 'The field's value can't be copied over because the field isn't editable. 'Have no choice but to propogate the conflict. QueryIsFieldConflict = True End If Else 'Don't need to do the next line because the Reconcile 'feature is already in the current version. 'vValueToUse = vReconcileValue End If Else If (UCase(<a href="http://pField.Name" target="_blank">pField.Name</a>) <> "SHAPE.AREA") And _ (UCase(<a href="http://pField.Name" target="_blank">pField.Name</a>) <> "SHAPE.LEN") Then 'Different in both versions - True conflict QueryIsFieldConflict = True End If End If End If Exit FunctionErrorHandler: 'Just take negative approach and say there is a conflict QueryIsFieldConflict = TrueEnd FunctionPrivate Function IsEqual(ByVal v1 As Variant, ByVal v2 As Variant) As Boolean On Error GoTo ErrorHandler Dim b1 As Boolean Dim b2 As Boolean b1 = IsNull(v1) b2 = IsNull(v2) ' Compare nulls before comparing values so VB doesn't complain If (b1 <> b2) Then '1 is Null and 1 isn't null. Not the same IsEqual = False ElseIf (b1 And b2) Then 'Both are NULL. Same IsEqual = True ElseIf (VarType(v1) = vbDataObject) Or (VarType(v1) = vbObject) Then 'Compare objects. Only works for objects supporting a couple of interfaces IsEqual = IsObjectEqual(v1, v2) Else IsEqual = CBool(v1 = v2) 'Use simple comparison of variant values End If Exit FunctionErrorHandler: 'Just take negative approach and say there're different IsEqual = FalseEnd FunctionPrivate Function IsObjectEqual(ByVal pUnk1 As IUnknown, _ ByVal pUnk2 As IUnknown) As Boolean If ((pUnk1 Is Nothing) And (pUnk2 Is Nothing)) Then 'Both are nothing. The same IsObjectEqual = True ElseIf ((pUnk1 Is Nothing) Xor (pUnk2 Is Nothing)) Then 'One is nothing. Not the same IsObjectEqual = False Else 'Both are something' 'If you add this next part, it will account for the case where two versions' 'tapped into the same complex edge. The reconcile will stitch up the' 'connectivity and geometry in these cases. However, if the 2 lines just' 'had vertices added to them, only one version of the vertices will be in' 'the final feature.' 'Try IRelationalOperator.Equals' If (TypeOf pUnk1 Is IRelationalOperator) And (TypeOf pUnk2 Is IRelationalOperator) Then' Dim pRelOp As IRelationalOperator' Set pRelOp = pUnk1' IsObjectEqual = pRelOp.Equals(pUnk2)' Set pRelOp = Nothing' 'Try IClone' ElseIf (TypeOf pUnk1 Is IClone) And (TypeOf pUnk2 Is IClone) Then If (TypeOf pUnk1 Is IClone) And (TypeOf pUnk2 Is IClone) Then Dim pClone As IClone Set pClone = pUnk1 IsObjectEqual = pClone.IsEqual(pUnk2) 'Good for Geometry and GraphicElements Set pClone = Nothing 'Must just use "is", not much chance here... Else IsObjectEqual = CBool(pUnk1 Is pUnk2) 'Last chance, try object comparison End If End IfEnd Function