Export (0) Print
Expand All

Chapter 30 - Creating Merge Replication Custom Conflict Resolvers Using Visual Basic

Microsoft® SQL Server™ 2000 includes several merge replication conflict resolution options, such as a merge text conflict resolver, an averaging conflict resolver, several DATETIME conflict resolvers, and other commonly used conflict resolvers. In the majority of merge replication conflicts, one of these built-in solutions will resolve the conflicts that may occur as part of merge replication. However, when a unique business need requires customized logic to determine the final merged data at Publisher and Subscriber sites, you can write an application that resolves the conflict according to specified business rules.

When writing custom conflict resolver applications, you will need to:

  • Define the conditions you want to handle with the application logic. 

  • Determine the type of change condition that is currently being handled. 

  • Initialize the source and destination information. 

  • Gather column information as to which column has changed if any special resolver tracker has been implemented, such as column tracking. 

  • Determine what phase the merge process is in: upload or download. 

  • Determine what data should be the winning data in a change. 

  • Propagate the data to the matching table on the other server and overwrite the losing data. 

To help you accomplish these steps, this chapter includes sections on using the Microsoft SQL Replication Conflict Resolver Library, learning to register a custom conflict resolver, and examining some merge replication custom conflict resolver samples.

The merge replication conflict resolvers discussed in this chapter are written in Microsoft Visual Basic®. An intermediate-level understanding of Visual Basic, as well as a beginning understanding of Component Object Model (COM) and Interface Definition Language (IDL), is assumed.

Using the Microsoft SQL Replication Conflict Resolver Library

Cc917657.spacer(en-us,TechNet.10).gif Cc917657.spacer(en-us,TechNet.10).gif

To write a merge replication custom conflict resolver, use the Microsoft SQL Replication Conflict Resolver Library. It is a DLL file that is installed as part of SQL Server 2000. This library of methods enables your application to respond as changes are applied during synchronization.

The Microsoft SQL Replication Conflict Resolver Library contains methods available to retrieve data and commit data between servers. To use the library in your merge replication custom conflict resolver applications, you need to:

  • Include the Microsoft SQL Replication Conflict Resolver Library in a Visual Basic application. 

  • Implement the IVBCustomResolver interface. 

  • Understand the methods in the IReplRowChange interface. 

  • Understand the methods in the IConnectionInfo interface. 

  • Understand the enumerated constants in the library. 

The Microsoft SQL Replication Conflict Resolver Library file is replrec.dll. It provides methods to return information from SQL Server to the application, including information about changes, details on how the rows are affected, details on which columns differ, and connection information about the Publisher and Subscriber.

It also contains methods that perform actions, such as evaluating a change to a table, determining winning data and placing it into a table, or removing data from a table.

The following diagram shows a COM representation of the Microsoft SQL Replication Conflict Resolver Library object and its three interfaces: IVBCustomResolver, IReplRowChange, and IConnectionInfo.

Cc917657.rcr01(en-us,TechNet.10).gif 

Adding the Microsoft SQL Replication Conflict Resolver Library to Visual Basic

To include the Microsoft SQL Replication Conflict Resolver Library in a Visual Basic application, your application must be a project of type ActiveX® DLL, and you must add the SQL Merge Conflict Resolver component to your project.

If you install SQL Server 2000 to the default location, the SQL Merge Conflict Resolver component will be in C:\Program Files\Microsoft SQL Server\80\COM\. To add the component to your project, click the Project | References menu. In the References dialog box, click Microsoft SQL Replication Conflict Resolver Library.

Component

Reference

Library

SQL Merge Conflict Resolver

Microsoft SQL Replication Conflict Resolver Library

Replrec.dll

To get detailed information about the component once it has been added to the project in Visual Basic, inspect its type library in the Object Browser. In the Library menu, select the SQLResolver library. In the Classes pane, the SQL Resolver shows the three interfaces, IVBCustomResolver, IConnectionInfo, and IReplRowChange, as well as several predefined constants.

IVBCustomResolver Interface

The IVBCustomResolver interface, used in a new class module by using the Implements keyword, contains two methods that must be coded by the developer in the application: the GetHandledStates method and the Reconcile method.

GetHandledStates Method

Method Syntax 

GetHandledStates(ResolverBm As Long)

This method enables you to list the conditions that the resolver will handle. The REPOLE_CHANGE_TYPE enumerations listed become a logical OR of the change types the resolver supports. The GetHandledStates method is invoked once when the table is loaded by the merge process. Then, for every change that needs to be propagated, the custom resolver is invoked if the change is a state that is handled by the resolver.

Although this process is commonly referred to as a conflict resolver, the changes that can be handled include non-conflict changes, such as new rows inserted at the Subscriber. All the available conflict and non-conflict changes that can be handled are listed in the REPOLE_CHANGE_TYPE enumeration. For a complete list of change types available, see the Constants topic in this chapter.

Reconcile Method

Method Syntax 

Sub Reconcile(pRowChange As IReplRowChange, dwFlags As Long, pvReserved As 
IReplRowChange)

Use the Reconcile method to define the business logic that determines what data is applied to the losing table.

The important parameter for the Reconcile method is a reference to an IReplRowChange object, shown as the variable pRowChange in the method syntax. IReplRowChange is defined in an include file, sqlres.h. Through the supporting methods available in IReplRowChange, you can determine the columns in conflict, examine the conflicting data, and update the appropriate table with the winning data based on the criteria established in your Reconcile method code.

For best results when using the Reconcile method, it is important to understand the different stages of the merge process. The first stage that occurs is the upload of changes from the Subscriber to the Publisher. The second stage is a download of changes from the Publisher to the Subscriber. During the upload, the Subscriber is considered as the source of the change, and the Publisher is the destination. During the download, the Publisher is considered the source and the Subscriber is the destination. This means the variables that designate source and destination change depending on the stage of the merge process.

When a custom resolver is a Visual Basic application, conflicts are resolved immediately after the application executes the appropriate resolution action. If the user wishes to review the changes before implementation, and then either accept the resolution or resubmit the changes, it is possible to do so. The option is available to write the losing row to a conflict table named conflict_<PublicationName>_<ArticleName>_usertablename, and to apply the winning row to the appropriate table. The custom resolver logs a special message to the conflict table that provides context information, which the user can evaluate before making a final decision about accepting the changes.

During coding in the Reconcile method, you will usually use some of the enumerations that are available as constants defined in the SQL Merge Conflict Resolver library component. It is recommended you use symbols for these enumerations whenever possible, instead of using hard-coded constants.

IReplRowChange and IConnectionInfo Interfaces

The IReplRowChange and IConnectionInfo interfaces provide methods that can be called during use of your merge replication custom conflict resolver application. The methods provide three functions:

  • Getting table, column, and connection information for the Publisher and Subscriber. 

  • Getting conflict information. 

  • Performing resolution actions. 

Here you will find a description of what each method does, as well as the Visual Basic signature and the IDL semantics for each method. The IDL semantics are provided as a quick reference for parameter direction.

IReplRowChange Interface and Methods

The IReplRowChange interface contains methods that deliver core replication functionality, such as the ability to query column values and to copy rows from source database to destination database. The methods available in this interface are called from the custom resolver application to return data used in decision-making logic, or to gather information about the database and tables and about the column in conflict.

Many of the methods use a ColumnID parameter. The ColumnID contains a number that represents the position of the column in the table, ranging from 1 to <number of columns>. This number is used as a parameter to methods instead of the column name.

If the table is vertically partitioned, a column position in the table at the Subscriber does not necessarily match what the column position value would be in the publishing table at the Publisher. For example, if a table contains five columns, but column 3 is not published, ColumnID=4 corresponds to the last column of the table. The following sections give the Visual Basic and IDL signatures of the methods.

Summary of Methods in IReplRowChange

Method

Description

CopyColumnFromSource

Sets the destination column to contain the same value as the respective source column.

CopyRowFromSource

Sets the destination row to contain the same data as is contained in the source row.

DeleteRow

Deletes the destination row.

DoDummyUpdate

Updates source or destination row meta data . This allows a subsequent merge process to pick up a change as a new change.

ForceRememberChange

Called before invoking IReplRowChange operations that alter the destination row.

GetChangeType

Returns information regarding the type of change that occurred.

GetColumnAttributes

Returns a bitmap indicating if column is an identity column and/or updatable.

GetColumnDatatype

Returns the column type.

GetColumnName

Returns the column name.

GetColumnStatus

Returns the column status.

GetDestinationColumnValue

Returns the value of the column from the destination table.

GetDestinationConnectionInfo

Returns connection information about the destination.

GetDestinationOwnerName

Returns the owner name of the destination table.

GetErrorInfo

Returns a detailed error code and description if the resolver has been invoked to handle an error situation.

GetExtendedError

Returns additional information about the error, such as whether the error was a duplicate key or a unique index violation.

GetNumColumns

Returns the number of columns in the base table.

GetPriorityWinner

Returns a value indicating which one has the higher priority, the source or the destination.

GetResolverProcedureName

Returns the resolver-specific information (for example, a column name).

GetRowGuidColName

Returns the name of the column in the base table that is the uniqueidentifier column used in merge replication.

GetRowIdentifier

Returns the uniqueidentifier for the row in conflict.

GetSourceColumnValue

Returns the value of the column from the source table.

GetSourceConnectionInfo

Returns connection information about the source.

GetTableName

Returns the name of the table in conflict.

GetTableOwnerName

Returns the owner name of the table.

InsertRow

Inserts the row at the destination.

LogConflict

Indicates whether the conflict should be logged, where, and what message to include.

LogError

Logs the error and an optional description.

UpdateRow

Updates the destination row.

Methods in the IReplRowChange Interface

CopyColumnFromSource 

(ColumnId As Long)Invoke this method if the corresponding destination column should be set to the same value contained in the source column referenced by the input parameter ColumnID.IDL SemanticsHRESULT CopyColumnFromSource (INTEGERTYPE ColumnId)

CopyRowFromSource() 

Invoke this method if the source is the conflict winner. The row at the destination will then be set to the same values as the source row.IDL SemanticsHRESULT CopyRowFromSource ()

DeleteRow() 

Invoke this method to delete the row at the destination. This method does not automatically delete the row at the source. It is used if a delete at the source conflicts with an update at the destination, and the delete is the winner.IDL SemanticsHRESULT DeleteRow ()

DoDummyUpdate(
fUpLineage As REPOLE_BOOL,
fAtPublisher As REPOLE_BOOL)

Updates the row meta data at either the source or the destination. Invoke this method at one of the two nodes to make sure the resulting row is propagated back to the originating node. The parameter fAtPublisher is used to determine whether the meta data to be updated is at the Publisher or the Subscriber. Set to TRUE to update at the Publisher. Set to FALSE to update at the Subscriber. Consider, for example, the scenario of a merge replication conflict in which the destination is the conflict winner. Calling DoDummyUpdate on the destination (having fAtPublisher=TRUE in the upload phase, FALSE otherwise) ensures the losing source row gets the values of the winning destination row as soon as it becomes the destination itself. Thus, if the Subscriber loses during upload, the DoDummyUpdate method guarantees the Publisher's row will be downloaded to the Subscriber during the next phase.Calling the method on the source can be used in error situations, when a resend should be forced. You might need to resend, for example, when you are using a Subscriber-always-wins resolver, but the upload of the Subscriber change has failed because the Publisher inserted a row with the same primary key. The download of the inserted row from the Publisher will fail due to the same reason, leading to the deletion of the inserted row at the Publisher. Therefore, the subsequent upload of the row that originated at the Subscriber will succeed when resending is forced.Set fUpLineage to TRUE to keep version information about the changed row. If you are unsure what value to use for the parameter, use TRUE.IDL SemanticsHRESULT DoDummyUpdate ([in] BOOLTYPE fUpLineage, [in] BOOLTYPE fAtPublisher)

ForceRememberChange() 

Call this method before invoking IReplRowChange operations that alter the destination row, such as CopyRowFromSource(), CopyColumnFromSource(), or DeleteRow(), if the conflict resolver allows an update/insert/delete at a Subscriber to win over an update/insert/delete at either the Publisher or another Subscriber which has since then already merged with the Publisher.IDL SemanticsHRESULT ForceRememberChange()

GetChangeType(
pChangeType As REPOLE_CHANGE_TYPE)

Returns what type of change occurred. The value returned is one of the enumerated constants from REPOLE_CHANGE_TYPE.IDL SemanticsHRESULT _stdcall GetChangeType([out] REPOLE_CHANGE_TYPE* pChangeType)

GetColumnAttributes(
ColumnId As Long,

PlColumnAttributes As REPOLE_COLUMN_ATTRIBUTES)Returns a bitmap of the enumerated constants from REPOLE_COLUMN_ATTRIBUTES into plColumnAttributes, for the column being referenced by the input parameter ColumnID. The bitmap indicates whether the referenced column is an identity column and/or an updatable column. It can be both. Check the results with *plColumnAttributes & REPOLEColumnAttribute_Updatable, or *plColumnAttributes & REPOLEColumnAttribute_Identity, respectively.IDL SemanticsHRESULT _stdcall GetColumnAttributes(long ColumnId, [out] REPOLE_COLUMN_ATTRIBUTES* plColumnAttributes)

GetColumnDatatype(
ColumnId As Long,
plDataType As REPOLE_SQL_DATATYPE)

Returns a value in plDataType that indicates what type of column is being referenced by the input ColumnID parameter. The type of column returned is one of the enumerated constants from REPOLE_SQL_DATATYPE.IDL SemanticsHRESULT _stdcall GetColumnDatatype(long ColumnId, [out] REPOLE_SQL_DATATYPE* plDataType)

GetColumnName(
ColumnId As Long,
pColumnName As String,
cbColumnName As Long)

Returns the name of the column being referenced by the input parameter ColumnID, into pColumnName. The input parameter cbColumnName gives a buffer size for pColumnName. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetColumnName(long ColumnId, [out] LPWSTR pColumnName, long cbColumnName)

GetColumnStatus(
ColumnId As Long,
pColStatus As REPOLE_COLSTATUS_TYPE)

Returns a value into pColStatus that indicates the status of the column being referenced by the input ColumnID parameter. The status of the column returned is one of the enumerated constants from REPOLE_COLSTATUS_TYPE.IDL SemanticsHRESULT _stdcall GetColumnStatus(
long ColumnId,
[out] REPOLE_COLSTATUS_TYPE* pColStatus)

GetDestinationColumnValue(
ColumnId As Long,
pvBuffer,
cbBufferMax As Long,
pcbBufferActual As Long)

Returns the value of the column, referenced by the ColumnID parameter, into pvBuffer. The column value returned is the value of the column at the destination table. The output parameter pcbBufferActual returns the number of bytes that the column value uses. The input parameter cbBufferMax indicates the size of pvBuffer. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetDestinationColumnValue(long ColumnId, [out] VARIANT* pvBuffer, [in] long cbBufferMax, [out] long* pcbBufferActual)

GetDestinationConnectionInfo(
ppDestinationConnectionInfo As IConnectionInfo,
pfIsPublisher As REPOLE_BOOL)

Returns a pointer to the object that contains all the connection information about the destination in the ppDestinationConnectionInfo parameter. This variable can then be used to make all the calls in the IConnectionInfo object. For example, this is the line of code that initializes the IConnectionInfo variable from the AdditiveResolver sample:Call rrc.GetDestinationConnectionInfo(DestConnectionInfo, DestIsPublisher)Once initialized, the DestConnectionInfo variable can be used as the qualifier to all the methods available in the IConnectionInfo object, by using:Call DestConnectionInfo.GetServerName(stSubscriber, Len(stSubscriber))The GetDestinationConnectionInfo method also returns a Boolean, into pfIsPublisher, that indicates whether or not the Publisher is the destination. TRUE indicates that the system is in the upload phase and the Publisher is the destination, not the source. FALSE indicates that the system is in the download phase and the Publisher is the source, not the destination. IDL SemanticsHRESULT _stdcall GetDestinationConnectionInfo([out] IConnectionInfo** ppDestinationConnectionInfo, [out] REPOLE_BOOL* pfIsPublisher)

GetDestinationOwnerName(
pDestOwnerName As String,
cbDestName As Long)

Returns the name of the owner of the destination table into pDestOwnerName. The input parameter cbDestName indicates the size of pDestOwnerName. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetDestinationOwnerName([out] LPWSTR pDestOwnerName, long cbDestName)

GetErrorInfo(
pErrCode As Long,
pErrText As String)

Returns the error code into pErrCode and the string description of the error into pErrText.IDL SemanticsHRESULT _stdcall GetErrorInfo([out] long* pErrCode, LPWSTR pErrText)

GetExtendedError(
pExtError As REPOLE_EXTENDEDERROR_TYPE)

Returns additional information about the error, such as whether the error was a duplicate key or a unique index violation. The value returned is one of the enumerated constants from REPOLE_EXTENDEDERROR_TYPE.IDL SemanticsHRESULT GetExtendedError ([out] REPOLE_EXTENDEDERROR_TYPE* pExtError)

GetNumColumns(
pdwColumnCount As Long)

Finds the number of columns in the base table. If there is a vertical partition, the number of columns in the table may not match the number of columns in the underlying table. For example, if a table contains five columns, but column 3 is not published, ColumnID=4 corresponds to the last column of the table.IDL SemanticsHRESULT _stdcall GetNumColumns([out] long* pdwColumnCount)

GetPriorityWinner(
pPriorityWinner As REPOLE_PRIORITY_TYPE)

Returns a value indicating if the source or destination has the higher priority, using one of the enumerated constants from REPOLE_PRIORITY_TYPE. This method always returns the source or the destination as the winner. With equal priorities, the default winner is the Publisher. The value REPOLE_Priority_Equal is not used. IDL SemanticsHRESULT _stdcall GetPriorityWinner([out] REPOLE_PRIORITY_TYPE*pPriorityWinner)

GetResolverProcedureName(
pResolverProcedureName As String,
cbResolverProcedureName As Long)

Retrieves resolver-specific information into pResolverProcedureName. For example, if the merge conflict process is focused on a particular column that has been specified in the Resolver tab of the table properties, this method returns that column name. cbResolverProcedureName indicates the size of the buffer. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetResolverProcedureName([out] LPWSTR pResolverProcedureName, long cbResolverProcedureName)

GetRowGuidColName(
pRowGuidColName As String,
cbRowGuidColName As Long)

Retrieves the name of the column in the base table, which is the uniqueidentifier column used in merge replication. The input parameter cbRowGuidColName indicates the size of the buffer. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetRowGuidColName([out] LPWSTR pRowGuidColName, long cbRowGuidColName)

GetRowIdentifier(
pRowGuid As REPLGUID)

Returns the row uniqueidentifier, which is used to uniquely identify the row.IDL SemanticsHRESULT _stdcall GetRowIdentifier([out] REPLGUID* pRowGuid)

GetSourceColumnValue(
ColumnId As Long,
pvBuffer,
cbBufferMax As Long,
pcbBufferActual As Long)

Returns the value of the column, referenced by the ColumnID parameter, into pvBuffer. The column value returned is the value of the column at the source table. The parameter pcbBufferActual returns the number of bytes the column value uses. The input parameter cbBufferMax indicates the size of pvBuffer. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetSourceColumnValue(long ColumnId, [out] VARIANT* pvBuffer, [in] long cbBufferMax, [out] long* pcbBufferActual)

GetSourceConnectionInfo(
ppSourceConnectionInfo As IConnectionInfo,
pfIsPublisher As REPOLE_BOOL)

Returns a pointer to the object that contains all the connection information about the source in the ppSourceConnectionInfo parameter. This variable can then be used to make all the calls in the IConnectionInfo object. For example, this is the line of code that initializes the IConnectionInfo variable from the AdditiveResolver sample:Call rrc.GetSourceConnectionInfo(SrcConnectionInfo, SrcIsPublisher)Once initialized, the SrcConnectionInfo can be used as the class identifier to call all the methods available in the IConnectionInfo object, by using:Call SrcConnectionInfo.GetServerName(stPublisher, en(stPublisher))The GetSourceConnectionInfo method also returns a Boolean that indicates whether or not the Publisher is the source. TRUE indicates that the system is in the download phase and the Publisher is the source, not the destination. FALSE indicates that the system is in the upload phase and the Publisher is the destination, not the source. IDL SemanticsHRESULT _stdcall GetSourceConnectionInfo([out] IConnectionInfo** ppSourceConnectionInfo, [out] REPOLE_BOOL* pfIsPublisher)

GetTableName(
pTableName As String,
cbTableName As Long)

Returns the name of the table, against which the conflict is occurring, into pTableName. The parameter cbTableName is an input parameter that gives a buffer size for pTableName. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetTableName([out] LPWSTR pTableName, long cbTableName)

GetTableOwnerName(
pOwnerName As String,
cbOwnerName As Long)

Returns the name of the table owner into pOwnerName. The input parameter cbOwnerName gives a buffer size for pOwnerName. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetTableOwnerName([out] LPWSTR pOwnerName, long cbOwnerName)

InsertRow() 

Inserts the row at the destination.IDL SemanticsHRESULT InsertRow ()

LogConflict(
bLogSourceConflict As REPOLE_BOOL,
ConflictType As REPOLE_CONFLICT_TYPE,
bOnlyLogIfUpdater As REPOLE_BOOL,
[pszConflictMessage As String],
[bLogConflictOnUpload As REPOLE_BOOL])

Takes input parameters that indicate whether the conflict should be logged, specifications on what message to log, and where the log is kept.The first parameter, bLogSourceConflict, is a Boolean indicating whether or not to log the conflict at the source.If bOnlyLogIfUpdater is set to TRUE, a conflict is logged only if the database that has the losing version actually created that version. Thus, if a Publisher propagates a change to multiple Subscribers and then receives a change that causes a conflict and makes the version at all of those Subscribers lose, a conflict will not be logged for each of those Subscribers, because they would not have made the losing change. They merely would have received it from the Publisher, due to a change from some other Subscriber.If bOnlyLogIfUpdater is FALSE, the losing version is logged regardless of whether the replica made the losing update.The input parameter ConflictType is the message to log. The optional input parameter pszConflictMessage can be used as additional text to the conflict message being logged. This allows the conflict message to be customized with additional information.The optional input parameter bLogConflictOnUpload does not need to be used. It is a default parameter that is not used by a custom resolver.IDL SemanticsHRESULT _stdcall LogConflict([in] REPOLE_BOOL bLogSourceConflict, [in] REPOLE_CONFLICT_TYPE ConflictType, [in] REPOLE_BOOL bOnlyLogIfUpdater, [in, optional, defaultvalue("")] BSTR pszConflictMessage, [in, optional, defaultvalue(0)] REPOLE_BOOL bLogConflictOnUpload)

LogError(
ChangeType As REPOLE_CHANGE_TYPE,
[pszErrorMessage As String])

Logs an error, such as a duplicate primary key error. It logs the input parameter ChangeType and the text in the optional input parameter pszErrorMessage string, as the description.IDL SemanticsHRESULT LogError ([in] REPOLE_CHANGE_TYPE ChangeType, [in, optional, defaultvalue("")] BSTR pszErrorMessage)

UpdateRow() 

Updates the row at the destination. IDL SemanticsHRESULT UpdateRow ()

IConnectionInfo Interface and Methods

The methods available in IConnectionInfo are called from the merge replication custom conflict resolver application to return information about the database and tables. The IConnectionInfo interface is also used when a resolver needs to access a stored procedure. A limitation of the IConnectionInfo interface is that only the GET methods are accessible to user-implemented resolvers. Although the Object Browser shows many SET methods, only the GET methods are documented.

Many of the methods use a ColumnID parameter. The ColumnID contains a number that represents the position of the column in the table, ranging from 1 to <number of columns>. This number is used as a parameter to methods instead of the column name.

If the table is vertically partitioned, a column position in the table at the Subscriber does not necessarily match what the column position value would be in the underlying table at the Publisher. For example, if a table contains five columns, but column 3 is not published, ColumnID=4 corresponds to the last column of the table.

Qualification of Method Calls

The methods in IConnectionInfo return information about the databases and tables involved in the merge process. The methods can return information about the source or the destination. To specify which one you want information about, qualify the procedure call with a variable. For example, this code returns information about the destination:

Call DestConnectionInfo.GetServerName(stPublisher, Len(stPublisher))

This code returns information about the source:

Call SrcConnectionInfo.GetServerName(stPublisher, Len(stPublisher))

Although the same method is called (GetServerName), the distinction regarding what it returns is specified in the qualifier.

To initialize the qualifiers, use the GetDestinationConnectionInfo in the IReplRowChange interface to initialize the DestConnectionInfo variable. Use the GetSourceConnectionInfo method in the IReplRowChange interface to initialize the SrcConnectionInfo variable.

Summary of Methods in IConnectionInfo

Method

Description

GetApplicationName

Returns the name of the application using the connection.

GetBcpBatchSize

Returns a value that indicates the setting of the batch size of commit.

GetCatalog

Returns the name of the catalog.

GetCodePage

Returns the current CodePage setting for the server.

GetComparisonStyle

Returns a value that indicates the SQL collation.

GetConnectName

Returns the connection name.

GetDatabase

Returns the database name.

GetDatabaseStatus

Returns the database status.

GetDatasource

Returns the data source name.

GetDatasourcePath

Returns the path to the .mdb file.

GetDataSourceType

Returns the type of data source.

GetDBCreatedThisSession

Returns a value that indicates whether or not the database has been created in this session.

GetHostName

Returns the host name being used in the IConnectionInfo object.

GetInternetAddress

Returns the Internet address.

GetInternetNetwork

Returns the NetLibrary to use when connecting.

GetLCID

Returns the preferred locale ID value.

GetLogin

Returns into Login the login currently in use if using SQL Server Authentication. If using Windows Authentication, the value returned to the Login parameter is an empty string.

GetLoginTimeout

Returns the number of seconds the system will wait before returning from a failed login attempt.

GetMajorVersion

Returns the product major version number.

GetMinorVersion

Returns the product minor version number.

GetPacketSize

Returns the packet size, in bytes.

GetPassword

Returns the current IConnectionInfo object password.

GetProviderName

Returns the OLE DB provider name.

GetProviderString

Returns the OLE DB property provider string.

GetQueryTimeout

Returns the number of seconds of the time-out value for queries against a server.

GetSecurityMode

Returns the security mode being employed to connect to SQL Server by the Windows user or group of users.

GetServerName

Returns the server name.

GetServerRole

Returns a string that indicates whether the server role is as a Subscriber, Distributor, or Publisher.

GetUseInprocLoader

Returns a value indicating whether or not the agent is using inproc loader (BULK INSERT statement) to load the data from bcp files into tables.

Methods in the IConnectionInfo Interface

GetApplicationName( 

ApplicationName As String,
cbApplicationName As Long)Returns the name of the application that uses this connection into ApplicationName (for example, "Merge Agent"). The input parameter cbApplicationName indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetApplicationName([out] LPWSTR ApplicationName, long cbApplicationName)

GetBcpBatchSize( 

plBcpBatchSize As Long)Returns into plBcpBatchSize a long that indicates the setting of the batch size of commit.IDL SemanticsHRESULT _stdcall GetBcpBatchSize([out] long* plBcpBatchSize)

GetCatalog( 

Catalog As String,
cbCatalog As Long)Returns into Catalog the name of the catalog. The input parameter cbCatalog indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetCatalog([out] LPWSTR Catalog, long cbCatalog)

GetCodePage( 

plCodePage As Long)Returns into plCodePage the current CodePage setting for the server. For more information on CodePage, see "Collations" in SQL Server Books Online.IDL SemanticsHRESULT _stdcall GetCodePage([out] long* plCodePage)

GetComparisonStyle( 

plComparisonStyle As Long)Returns into plComparisonStyle an integer that indicates the SQL collation. For more information on collation, see "SQL Server Collation Fundamentals" in SQL Server Books Online. IDL SemanticsHRESULT _stdcall GetComparisonStyle([out] long* plComparisonStyle)

GetConnectName( 

ConnectName As String,
cbConnectName As Long)Returns the connection name into ConnectName. The input parameter cbConnectName indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetConnectName([out] LPWSTR ConnectName, long cbConnectName)

GetDatabase( 

Database As String,
cbDatabase As Long)Returns into Database the name of the database. The input parameter cbDatabase indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetDatabase([out] LPWSTR Database, long cbDatabase)

GetDatabaseStatus( 

plDatabaseStatus As Long)Returns a value into plDatabaseStatus that is one of the enumerated constants from REPOLE_DBAddoption.IDL SemanticsHRESULT _stdcall GetDatabaseStatus([out] long* plDatabaseStatus)

GetDatasource( 

Datasource As String,
cbDatasource As Long)Returns into Datasource the name of the data source. The input parameter, cbDatasource, indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetDatasource([out] LPWSTR Datasource, long cbDatasource)

GetDatasourcePath( 

DatasourcePath As String,
cbDatasourcePath As Long)If the data source is a Jet database, this method returns the path to the .mdb file into DatasourcePath. This is the same data stored in the Datasource_path column, which you can see by running the stored procedure sysmergesubscriptions. The input parameter, cbDatasourcePath, indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetDatasourcePath([out] LPWSTR DatasourcePath, long cbDatasourcePath)

GetDataSourceType( 

pRetValue As REPOLE_DATASOURCE_TYPE)Returns the type of data source into pRetValue. The value returned is one of the enumerated constants from REPOLE_DATASOURCE_TYPE. IDL SemanticsHRESULT _stdcall GetDataSourceType([out] REPOLE_DATASOURCE_TYPE* pRetValue)

GetDBCreatedThisSession( 

pbDBCreatedThisSession As Long)Returns into pbDBCreatedThisSession a value that indicates whether the database has been created in this session. A value of 0 indicates FALSE, or not created this session, while a value of 1 indicates TRUE, the database was created this session.IDL SemanticsHRESULT _stdcall GetDBCreatedThisSession([out] long* pbDBCreatedThisSession)

GetHostName( 

HostName As String,
cbHostName As Long)Returns the host name being used in the IConnectionInfo object into HostName. The input parameter cbHostName indicates the buffer size. HRESULT returns an error if the buffer is too small. IDL SemanticsHRESULT _stdcall GetHostName([out] LPWSTR HostName, long cbHostName)

GetInternetAddress( 

InternetAddress As String,
cbInternetAddress As Long)Returns the Internet address as a string into InternetAddress. The input parameter cbInternetAddress indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetInternetAddress([out] LPWSTR InternetAddress, long cbInternetAddress)

GetInternetNetwork( 

InternetNetwork As String,
cbInternetNetwork As Long)Returns into InternetNetwork the NetLibrary to use when connecting. The NetLibrary string does not contain the .dll extension. This option is useful when configuring the Merge Agent to connect over the Internet. The input parameter cbInternetNetwork indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetInternetNetwork([out] LPWSTR InternetNetwork, long cbInternetNetwork)

GetLCID( 

plLCID As Long)Returns a value into plLCID that indicates the preferred locale ID.IDL SemanticsHRESULT _stdcall GetLCID([out] long* plLCID)

GetLogin( 

Login As String,
cbLogin As Long)Returns into Login the login currently in use if you are using SQL Server Authentication. If you are using Windows Authentication, the value returned to the Login parameter is an empty string. The input parameter cbLogin indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetLogin([out] LPWSTR Login, long cbLogin)

GetLoginTimeout( 

plLoginTimeout As Long)Returns the number of seconds the system will wait before returning from a failed login attempt.IDL SemanticsHRESULT _stdcall GetLoginTimeout([out] long* plLoginTimeout)

GetMajorVersion( 

plMajorVersion As Long)Returns the major version number of the product into plMajorVersion. The value returned is one of the enumerated constants from REPOLE_SERVER_VERSION. IDL SemanticsHRESULT _stdcall GetMajorVersion(long* plMajorVersion)

GetMinorVersion( 

plMinorVersion As Long)Returns the minor version number of the product into plMinorVersion. The value returned is one of the enumerated constants from REPOLE_SERVER_MINOR_VERSION. IDL SemanticsHRESULT _stdcall GetMinorVersion(long* plMinorVersion)

GetPacketSize( 

pusPacketSize As Long)Returns the packet size, in bytes, into pusPacketSize. The default is 4096 bytes. For more information, see "network packet size Option" in SQL Server Books Online. IDL SemanticsHRESULT _stdcall GetPacketSize([out] unsigned long* pusPacketSize)

GetPassword( 

Password As String,
cbPassword As Long)Returns the password currently being used in the IConnectionInfo object into Password. The input parameter cbPassword indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetPassword([out] LPWSTR Password, long cbPassword)

GetProviderName( 

ProviderName As String,
cbProviderName As Long)Returns the OLE DB provider name into ProviderName. The input parameter cbProviderName indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetProviderName([out] LPWSTR ProviderName, long cbProviderName)

GetProviderString( 

ProviderString As String,
cbProviderString As Long)Returns the OLE DB provider string into ProviderString. The ProviderString property specifies the OLE DB provider-specific connection data required to implement a connection to the referenced OLE DB data source. The input parameter cbProviderString indicates the buffer size. HRESULT returns an error if the buffer is too small. IDL SemanticsHRESULT _stdcall GetProviderString([out] LPWSTR ProviderString, long cbProviderString)

GetQueryTimeout( 

plQueryTimeout As Long)Returns the number of seconds of the time-out value for queries against a server into plQUeryTimeout. IDL SemanticsHRESULT _stdcall GetQueryTimeout([out] long* plQueryTimeout)

GetSecurityMode( 

pRetValue As REPOLE_SECURITY_TYPE)Returns into pRetValue the security mode being employed to connect to SQL Server by the Windows user or group of users. The value returned is one of the enumerated constants from REPOLE_SECURITY_TYPE.IDL SemanticsHRESULT _stdcall GetSecurityMode([out] REPOLE_SECURITY_TYPE* pRetValue)

GetServerName( 

ServerName As String,
cbServerName As Long)Returns into ServerName the name of the server. The input parameter, cbServerName, indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetServerName([out] LPWSTR ServerName, long cbServerName)

GetServerRole( 

ServerRole As String,
cbServerRole As Long)Returns a string into ServerRole that indicates which server role is being used, Subscriber, Distributor, or Publisher. The input parameter cbServerRole indicates the buffer size. HRESULT returns an error if the buffer is too small.IDL SemanticsHRESULT _stdcall GetServerRole([out] LPWSTR ServerRole, long cbServerRole)

GetUseInprocLoader( 

pbUseInprocLoader As Long)Returns a value into pbUseInprocLoader indicating whether or not the agent is using inproc loader (BULK INSERT statement) to load the data from bcp files into tables. It returns FALSE if the agent is using ODBC BCP to load data from bcp files into the tables.IDL SemanticsHRESULT _stdcall GetUseInprocLoader([out] long* pbUseInprocLoader)

Constants

This section provides detail on the enumerated data types that are defined in the SQL Replication Conflict Resolver Library, and are used as parameters and return values to the methods in the SQL Merge Conflict Resolver component.

REPLGUID

The REPLGUID constants provide a class identifier that is a properly formatted GUID.

Constant

Description

Data1

Long

Data2

Short

Data3

Short

Data4

Unsigned char(8)

REPOLE_BOOL

The REPOLE_BOOL constants specify values that indicate true or false.

Constant

Value

Description

REPOLEBool_FALSE

0

Value is false.

REPOLEBool_TRUE

1

Value is true.

REPOLE_CHANGE_TYPE

The REPOLE_CHANGE_TYPE constants specify what the database operation (update, insert, delete) is, whether or not there is a conflict, and whether or not column tracking is active.

Constant

Value

Description

REPOLEChange_SubscriberInsert

0x00000001

Subscriber is inserting new row in upload phase.

REPOLEChange_PublisherInsert

0x00010000

Publisher is inserting new row in download phase.

REPOLEChange_SubscriberDelete_
NoConflict

0x00000002

Subscriber is deleting a row. No conflict detected.

REPOLEChange_PublisherDelete_
NoConflict

0x00020000

Publisher is deleting a row. No conflict detected.

REPOLEChange_SubscriberSystem
Delete

0x00000004

Subscriber is deleting the row due to reasons like primary key violations.

REPOLEChange_PublisherSystemDelete

0x00040000

Publisher is deleting the row due to reasons like primary key violations.

REPOLEChange_SubscriberDelete_
Conflict

0x00000008

Subscriber is deleting a row. Conflict detected.

REPOLEChange_PublisherDelete_
Conflict

0x00080000

Publisher is deleting a row. Conflict detected.

REPOLEChange_SubscriberRemove
FromPartial

0x00000010

Not used.

REPOLEChange_PublisherRemove
FromPartial

0x00100000

The publisher tells the subscriber to delete the row, because it is no longer in the partition.

REPOLEChange_SubscriberUpdate_
NoConflict

0x00000020

Subscriber is updating a row. No conflict detected.

REPOLEChange_PublisherUpdate_
NoConflict

0x00200000

Publisher is updating a row. No conflict detected.

REPOLEChange_SubscriberUpdate_
Conflict
WithDelete

0x00000040

Subscriber is updating a row and has a conflict with a delete coming from the Publisher.

REPOLEChange_PublisherUpdate_
ConflictWith
Delete

0x00400000

Publisher is updating a row and has a conflict with a delete coming from the Subscriber.

REPOLEChange_SubscriberUpdate_
ConflictColTrack

0x00000080

Subscriber is updating a specific column, column tracking is in effect, and the update has a conflict with a change coming from the Publisher.

REPOLEChange_PublisherUpdate_
ConflictColTrack

0x00800000

Publisher is updating a specific column, column tracking is in effect, and the update has a conflict with a change coming from the Subscriber.

REPOLEChange_SubscriberUpdate_
ConflictNoColTrack

0x00000100

Subscriber is updating a specific column, column tracking is not in effect, and the update has a conflict with a change coming from the Publisher.

REPOLEChange_PublisherUpdate_
ConflictNoColTrack

0x01000000

Publisher is updating a specific column, column tracking is not in effect, and the update has a conflict with a change coming from the Subscriber.

REPOLEChange_UploadInsertFailed

0x00000200

A row was inserted at the Subscriber, but the subsequent insertion at the Publisher failed.

REPOLEChange_DownloadInsertFailed

0x02000000

A row was inserted at the Publisher, but the subsequent insertion at the Subscriber failed.

REPOLEChange_UploadDeleteFailed

0x00000400

A row was deleted at the Subscriber, but the subsequent deletion at the Publisher failed.

REPOLEChange_DownloadDelete
Failed

0x04000000

A row was deleted at the Publisher, but the subsequent deletion at the Subscriber failed.

REPOLEChange_UploadUpdate
Failed

0x00000800

A row was updated at the Subscriber, but the subsequent update at the Publisher failed.

REPOLEChange_DownloadUpdate
Failed

0x08000000

A row was updated at the Publisher, but the subsequent update at the Subscriber failed.

REPOLEUpdateConflicts

 

The combination of:
(REPOLEChange_SubscriberUpdate_
ConflictColTrack |
REPOLEChange_PublisherUpdate_
ConflictColTrack |
REPOLEChange_SubscriberUpdate_
ConflictNoColTrack |
REPOLEChange_PublisherUpdate_
ConflictNoColTrack)

REPOLEAllConflicts

 

The combination of:
(REPOLEChange_SubscriberDelete_Conflict |
REPOLEChange_PublisherDelete_Conflict |
REPOLEChange_SubscriberUpdate_
ConflictWithDelete |
REPOLEChange_PublisherUpdate_
ConflictWithDelete |
REPOLEUpdateConflicts)

REPOLEAllErrors

 

The combination of:
(REPOLEChange_UploadInsertFailed |
REPOLEChange_DownloadInsertFailed |
REPOLEChange_UploadDeleteFailed |
REPOLEChange_DownloadDeleteFailed |
REPOLEChange_UploadUpdateFailed |
REPOLEChange_DownloadUpdateFailed)

REPOLEAllNonConflicts

 

The combination of:
(REPOLEChange_SubscriberInsert |
REPOLEChange_PublisherInsert |
REPOLEChange_SubscriberDelete_
NoConflict |
REPOLEChange_PublisherDelete_
NoConflict|
REPOLEChange_SubscriberSystemDelete |
REPOLEChange_PublisherSystemDelete |
REPOLEChange_SubscriberRemoveFrom
Partial |
REPOLEChange_SubscriberUpdate_
NoConflict |
REPOLEChange_PublisherUpdate_
NoConflict)

REPOLEAllChanges

 

The combination of:
(REPOLEAllConflicts | REPOLEAllErrors |
REPOLEAllNonConflicts)

REPOLE_COLSTATUS_TYPE

The REPOLE_COLSTATUS_TYPE constants specify the status of an individual column.

Constant

Value

Description

REPOLEColumn_NotUpdated

0x0001

No updates to column, or data values match.

REPOLEColumn_UpdatedNoConflict

0x0002

Column updated at source, no column-level conflict.

REPOLEColumn_UpdatedWithConflict

0x0003

Column updated at source, conflicts with change at destination.

REPOLEColumn_DifferNoTrack

0x0004

No column tracking information; data values are different.

REPOLE_COLUMN_ATTRIBUTES

The REPOLE_COLUMN_ATTRIBUTES constants specify whether the column is updatable, an identity column, or both.

Constant

Value

Description

REPOLEColumnAttribute_Updatable

0x0001

This column is updatable.

REPOLEColumnAttribute_Identity

0x0002

This column is an identity column.

Remarks

The values returned from methods that use this constant return a bitmap of the values, and because a column can be both updatable and an identity column, check the results with *plColumnAttributes & REPOLEColumnAttribute_Updatable, or *plColumnAttributes & REPOLEColumnAttribute_Identity, respectively.

REPOLE_CONFLICT_TYPE

The REPOLE_CONFLICT_TYPE constants specify a value that describes the type of conflict that occurred and if the failure occurred during the upload or download phase.

Constant

Value

Description

REPOLEConflict_Min

1

For internal use only.

REPOLEConflict_UpdateConflict

1

The two replicas made conflicting updates to the same row.

REPOLEConflict_ColumnUpdateConflict

2

The two replicas made conflicting updates to the same column of the same row.

REPOLEConflict_UpdateDeleteWinsConflict

3

An update conflicted with a delete, and the delete won.

REPOLEConflict_UpdateWinsDelete
Conflict

4

An update conflicted with a delete, and the update won.

REPOLEConflict_UploadInsertFailed

5

Corresponds to the respective REPOLE_CHANGE_TYPE.

REPOLEConflict_DownloadInsertFailed

6

Corresponds to the respective REPOLE_CHANGE_TYPE.

REPOLEConflict_UploadDeleteFailed

7

Corresponds to the respective REPOLE_CHANGE_TYPE.

REPOLEConflict_DownloadDeleteFailed

8

Corresponds to the respective REPOLE_CHANGE_TYPE.

REPOLEConflict_UploadUpdateFailed

9

Corresponds to the respective REPOLE_CHANGE_TYPE.

REPOLEConflict_DownloadUpdateFailed

10

Corresponds to the respective REPOLE_CHANGE_TYPE.

REPOLEConflict_ResolutionDone

11

For internal use only.

REPOLEConflict_Max

11

For internal use only.

REPOLE_DATASOURCE_TYPE

Because SQL Server 2000 offers the ability to replicate data to any heterogeneous data source that provides a 32-bit ODBC or OLE DB driver on either Microsoft Windows® 2000, Microsoft Windows NT® Server 4.0, or Windows 98 operating systems, the REPOLE_DATASOURCE_TYPE constants provide data source type values for the application. For more information, see "DATASOURCE_TYPE" in SQL Server Books Online.

Constant

Value

Description

REPOLEDataSource_Native

0x0000

Microsoft SQL Server Subscriber data source.

REPOLEDataSource_Jet

0x0002

Microsoft Jet 4.0 database.

The object browser shows more constants for this enumeration. They are not valid, however, in a Visual Basic merge replication conflict resolver application, and therefore are not listed here.

REPOLE_DBADDOPTION

The REPOLE_DBADDOPTION constants specify if the Subscriber database exists or if it must be created or attached, or if the subscription must be attached.

Constant

Value

Description

REPOLEExisting_Database

0x0000

Uses an existing Subscriber database.

REPOLECreate_Database

0x0001

Creates the Subscriber database (SQL Server Subscribers only).

REPOLEAttach_Database

0x0002

Attaches a Subscriber database file, typically an .mdf (SQL Server Subscribers only).

REPOLEAttach_Subscription

0x0003

Attaches a subscription file, typically an .msf (Microsoft Subscription File).

REPOLE_EXTENDEDERROR_TYPE

The REPOLE_EXTENDEDERROR_TYPE constants return additional error information.

Constant

Value

Description

REPOLEExtErrorNoneOrNotSpecified

0x00000000

All errors not specifically addressed.

REPOLEExtErrorDupKey

0x00000001

SQL Server error 2627: Violation of %ls constraint '%.*ls'. Cannot insert duplicate key in object '%.*ls'.

REPOLEExtErrorDupUniqueIndex

0x00000002

SQL Server error 2601: Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'.

REPOLE_PRIORITY_TYPE

The REPOLE_PRIORITY_TYPE constants return the assigned priority. For more information, see "Subscriber Types and Conflicts" in SQL Server Books Online.

Constant

Value

Description

REPOLEPriority_Source

0x0001

The source has the higher priority.

REPOLEPriority_Destination

0x0002

The destination has the higher priority.

REPOLEPriority_Equal

0x0003

The source and destination have equal priority.

Note If priorities are equal, you will receive REPOLEPriority_Source during download or REPOLEPriority_Destination during upload, instead of REPOLEPriority_Equal.

REPOLE_SECURITY_TYPE

These constants specify what kind of security is used when connecting to SQL Server.

Constant

Value

Description

REPOLESecurity_Min

0

For internal use only.

REPOLESecurity_Normal

0

Specifies SQL Server Authentication mode.

REPOLESecurity_Integrated

1

Specifies Windows Authentication mode.

REPOLESecurity_Mixed

2

Specifies Windows Authentication or SQL Server Authentication. SQL Server Authentication is provided for backward compatibility.

REPOLESecurity_Max

2

For internal use only.

REPOLESecurity_Invalid

-1

Indicates that the security mode is not specified. Security mode is retrieved from the Publisher.

Remarks

The terminology used in several of these constants contains some references for backward compatibility to SQL Server version 6.5. The terms, Windows Authentication and Mixed Mode, replace integrated security and mixed security, respectively. Standard security has no equivalent. For more information, see "Authentication Modes" in SQL Server Books Online.

REPOLE_SERVER_VERSION

This is an enumeration that describes what version of SQL Server is running.

Constant

Value

Description

REPOLEVersion_Invalid

-1

Unknown or not set.

REPOLEVersion_70RTM

10

SQL Server 7.0.

REPOLEVersion_70SP1

20

SQL Server 7.0 with Service Pack 1.

REPOLEVersion_70SP2

30

SQL Server 7.0 with Service Pack 2.

REPOLEVersion_70SP3

35

SQL Server 7.0 with Service Pack 3.

REPOLEVersion_80

40

SQL Server 2000.

REPOLE_SERVER_MINOR_VERSION

This is an enumeration that indicates the minor version number that is running.

Constant

Value

Description

REPOLEMinorVersion_Invalid

-1

Unknown or not set.

REPOLEMinorVersion_80Beta2

10

SQL Server 2000, Beta 2.

REPOLEMinorVersion_80EAP6

20

SQL Server 2000, Early Adopter Program 6.

REPOLEMinorVersion_80RTM

30

SQL Server 2000 Retail.

REPOLE_SQL_DATATYPE

This is an enumeration of the ODBC data types. For more information on the default ODBC data types and their descriptions, see the topic, SQL Data Types, in the Microsoft Open Database Connectivity (ODBC) section of the Microsoft Data Access Components (MDAC) SDK (available on the MSDN Library CD). Additionally, the ODBC SDK is available in Microsoft ODBC 3.0 Software Development Kit and Programmer's Reference from Microsoft Press®.

Constant

Value

REPOLEType_SQL_UNKNOWN_TYPE

0

REPOLEType_SQL_CHAR

1

REPOLEType_SQL_NUMERIC

2

REPOLEType_SQL_DECIMAL

3

REPOLEType_SQL_INTEGER

4

REPOLEType_SQL_SMALLINT

5

REPOLEType_SQL_FLOAT

6

REPOLEType_SQL_REAL

7

REPOLEType_SQL_DOUBLE

8

REPOLEType_SQL_DATETIME

9

REPOLEType_SQL_DATE

9

REPOLEType_SQL_INTERVAL

10

REPOLEType_SQL_TIME

10

REPOLEType_SQL_TIMESTAMP

11

REPOLEType_SQL_VARCHAR

12

REPOLEType_SQL_LONGVARCHAR

-1

REPOLEType_SQL_BINARY

-2

REPOLEType_SQL_VARBINARY

-3

REPOLEType_SQL_LONGVARBINARY

-4

REPOLEType_SQL_BIGINT

-5

REPOLEType_SQL_TINYINT

-6

REPOLEType_SQL_BIT

-7

REPOLEType_SQL_GUID

-11

Remarks

For any of the datetime and interval data types, this field returns the verbose data type: SQL_DATETIME or SQL_INTERVAL. The developer is responsible for knowing the concise data type, as there is no REPOLE_SQL_DATATYPE enumeration that maps directly to the individual ODBC data types.

Registering a Custom Conflict Resolver

Cc917657.spacer(en-us,TechNet.10).gif Cc917657.spacer(en-us,TechNet.10).gif

The merge replication custom conflict resolver must be registered in order to be recognized by SQL Server.

To Register a Merge Replication Custom Conflict Resolver 

In Visual Basic, go to the File menu and click Make <yourproject>.DLL. This will compile and register the application on the current computer. If the .DLL needs to be registered on a different computer, run REGSVR32 <yourproject>.DLL from the command prompt. The .DLL must be registered on the computer that is invoking the merge agent. If you are using this application with a push subscription, the resolver must be registered at the Distributor that is invoking the merge agent. Similarly, for pull subscriptions, the resolver must be registered at the Subscriber that is invoking the merge agent. To ensure the resolver is registered properly, run sp_enumcustomresolvers on the computer on which it is registered. If the application name is returned in the result set, it is registered properly.

Registering Custom Resolvers on a Cluster

When using custom conflict resolvers with merge replication on a failover cluster, register the custom resolver on all nodes of the failover cluster. This ensures the custom resolver will be able to load the resolver properly after a failover. Merge replication conflict resolvers that come with SQL Server are automatically registered.

Merge Replication Custom Conflict Resolver Samples

Cc917657.spacer(en-us,TechNet.10).gif Cc917657.spacer(en-us,TechNet.10).gif

The Merge Replication Custom Conflict Resolver (SampleResolver) sample is available on the SQL Server 2000 Resource Kit CD-ROM in the folder, \ToolsAndSamples\SampleResolver. The samples demonstrate the implementation of the SQL Replication Conflict Resolver Library in merge replication custom conflict resolver applications. Samples included are:

  • Additive Resolver 

  • Minimum Resolver 

The samples contain a SQL Script that will register the custom conflict resolvers.

Additive Resolver

The Additive Resolver is designed to handle several types of UPDATE conflicts. The Additive Resolver chooses the sum of the column values from the Publisher and Subscriber as the winning column value in an UPDATE conflict.

When a custom application is used to resolve conflicts on a particular column, the user is required to enter the name of the column when creating the publication using the Create Publication Wizard, or using the @resolver_info parameter of the sp_addmergearticle system stored procedure. For more information, see "Specifying a Custom Resolver" in SQL Server Books Online.

The IVBCustomResolver_Reconcile Method 

The IVBCustomResolver_Reconcile method is where the conflict logic is coded. It is necessary to gather all the data needed (the order in which the data is gathered is not critical) before invoking the resolve code. The resolve code is in the IVBCustomResolver_ComputeAdditiveValues method in the AdditiveResolver sample.

To gather the necessary data, the first task done in the Reconcile method is to determine what kind of change occurred. The type of change can be found by calling the method GetChangeType and passing to it a variable of type SQLResolver.REPOLE_CHANGE_TYPE. The value returned will be one of the REPOLE_CHANGE_TYPE variables.

The next task, which you will see in the sample, is to retrieve the data connection information. This is done by calling the GetSourceConnectionInfo and GetDestinationConnectionInfo methods. These two methods take, as their parameters, a variable declared as IConnectionInfo, as well as a variable defined as a Boolean (REPOLE_BOOL). The application then uses the GetRowIdentifier method to get the GUID of the row in the table. It then determines whether the merge process is being done in the upload phase or the download phase.

When a custom application is used to resolve conflicts on a particular column, the code retrieves the column name the user has entered by calling the GetResolverProcedureName method of IReplRowChange. The name of this function is somewhat of a misnomer, as it does not get a procedure name, but a column name. When that application has the column name, it needs to convert the name to a value that indicates the position of the column in the table. The application loops through all the columns in the table, comparing the retrieved column name to each column name in the table. When it finds a match, the application calls the IVBCustomResolver_ComputeAdditiveValues method, which determines the new column value.

The IVBCustomResolver_ComputeAdditiveValues Method 

The application first determines the status of the column in question by calling GetColumnStatus. This gives the following status options:

REPOLEColumn_DifferNoTrack

REPOLEColumn_NotUpdated

REPOLEColumn_UpdatedNoConflict

REPOLEColumn_UpdatedWithConflict

Depending on the state of the column, the application can then make a decision on how to proceed. In the sample, if the column has been updated at both source and destination, retrieve the value from both computers using calls to GetSourceColumnValue and GetDestinationColumnValue. The application then adds them together.

To put the desired value back into the table column, the application uses the SetColumn function. The SetColumn function does not commit the value. To commit the value to the table, the UpdateRow function must be called and changes to the entire row are committed.

For columns that have been updated without changes, the application copies the column data by using CopyColumnFromSource. Again, to commit the value to the table, call the UpdateRow function.

MinimumResolver

The MiminumResolver handles several types of conflicts. When an UPDATE conflict occurs, it determines the minimum value between the source and destination column values, and sets the minimum value as the winning value. If the column values match, then the winning data is based on priorities. For more information on assigning priorities in conflicts, see "Subscriber Types and Conflicts" in SQL Server Books Online.

The IVBCustomResolver_Reconcile Method 

The IVBCustomResolver_Reconcile method is where the conflict logic is coded. It is necessary to gather all the data needed (the order in which the data is gathered is not critical) before invoking the resolve code. The resolve code in this sample is in the IVBCustomResolver_ComputeMinimumValue method.

To gather the necessary data, the first task done in the Reconcile method is to determine what kind of change occurred. The type of change can be found by calling the method GetChangeType and passing to it a variable of type SQLResolver.REPOLE_CHANGE_TYPE. The value returned will be one of the REPOLE_CHANGE_TYPE variables.

The next task, which you will see in the sample, is to retrieve the data connection information. This is done by calling the GetSourceConnectionInfo and GetDestinationConnectionInfo methods. These two methods take, as their parameters, a variable declared as IConnectionInfo, as well as a variable defined as a Boolean (REPOLE_BOOL). The application then uses the GetRowIdentifier method to get the GUID of the row in the table. It then determines whether the merge process is being done in the upload phase or the download phase.

Since this application is designed to resolve conflicts in a particular column, the code retrieves the column name the user has entered by calling the GetResolverProcedureName method of IReplRowChange. The name of this function is somewhat of a misnomer, as it does not get a procedure name, but a column name. Now that the application has the column name, it must convert the name to a value that indicates the position of the column in the table. The application loops through all the columns in the table, comparing the retrieved column name to each column name in the table. When it finds a match, the application calls the IVBCustomResolver_ComputeMinimumValue method, which determines the new column value.

The IVBCustomResolver_ComputeMinimumValue Method 

The application first retrieves the values of the column from the source and the destination. Then IF/ELSE logic is used to determine which value is less than the other, or if they are equal. If they are equal, the application calls GetPriorityWinner to determine the winner.

To put the desired value back into the table column, the application uses the SetColumn function. The SetColumn function does not commit the value. To commit the value to the table, the UpdateRow function must be called and changes to the entire row are committed.

The application copies the column data by using CopyColumnFromSource, and uses the UpdateRow method to commit the value to the table.

To Run the Samples
  1. When the script in vbresolver_1.sql is finished, merge the data using Windows Synchronization Manager. From the Windows Start menu, click Start, select Programs, select Accessories, and then click Synchronize

  2. After the Subscription has been synchronized using the Merge Agent, use SQL Query Analyzer to open the file \ToolsAndSamples\SampleResolver\vbresolver_2.sql. When the script in vbresolver_2.sql is run, it will create an update conflict, which will then demonstrate the custom resolvers. 

Cc917657.spacer(en-us,TechNet.10).gif

Was this page helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft