Changes between Version 1 and Version 2 of FDORfc19


Ignore:
Timestamp:
Apr 30, 2008, 12:28:25 PM (16 years ago)
Author:
gregboone
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • FDORfc19

    v1 v2  
    2323== Overview ==
    2424
     25This document contains a design for software and file version handling strategies for FDO. The versions dealt by this document are:
     26
     27        • Version of FDO software[[br]]
     28        • FDO provider versions[[br]]
     29        • XML configuration file versions[[br]]
     30
    2531== Motivation ==
    2632
    27 == Implications ==
     33In FDO 3.x, a number of issues arose regarding the handling of Provider versions. There were a number of concerns as to how these versions should be handled going forward. The main purpose of this design is to resolve these issues so that customers and client applications can easily upgrade to new FDO software releases as they become available.
     34
     35== Requirements ==
     36
     37=== FDO and Provider Versions ===
     38
     39The main requirement is to ensure that, when a client asks FDO to load a particular provider, the version that is loaded is compatible with the current FDO.
     40
     41When client stores connection information, it typically includes the provider name. This name is tied to a particular provider version.  However, this is problematic if the next major revision of the client software loads the provider for a particular connection, using the provider name stored in the client specific file.
     42
     43The above would attempt to retrieve the 3.0 version of the provider, which is likely binary incompatible with the next major revision of the client, which would be compatible with FDO 4.0. This can be worked around, by changing the version part of the provider name from 3.0 to 4.0, before requesting to load it. However, it would be good to streamline this so that FDO clients do not have to keep track of what all the current provider versions are.
     44
     45In FDO 3.1, work was done to address this by allowing clients to omit the version parts of the provider name when requesting to load it. In this case, the latest registered version of the provider is retrieved. However, there is no guarantee that this version of the provider is binary-compatible with the current version of FDO.
     46
     47FDO consists of a number of core libraries (e.g. Fdo.dll, !FdoCommon.dll, etc ) plus a number of providers. Each provider handles a different type of data. The list of providers is extensible (customers can write their own). Each provider must be registered in the provider registry, in order for the FDO core to be able to find it. The provider registry can contain multiple versions of the same provider.
     48
     49Clients load providers via the FDO Feature Access Manager (FAM). The client supplies the provider name and the FAM finds the provider in the registry.  The provider name can contain the name parts plus optional version number (e.g. "OSGeo.SDF" (no version), "OSGeo.SDF.3" (name plus major version), "OSGeo.SDF.3.1" (name plus major and minor version)).
     50
     51Currently, the FAM retrieves the latest registered version of the requested provider. For example, if the registry contains the following providers:
     52
     53        OSGeo.SDF.3.0[[br]]
     54        OSGeo.SDF.3.1[[br]]
     55        OSGeo.SDF.3.2[[br]]
     56        OSGeo.SDF.4.0[[br]]
     57        OSGeo.SDF.5.0[[br]]
     58
     59the following table shows which provider is returned by the FAM, depending on the requested name.
     60
     61||'''Client Requested'''||'''FAM Returns'''||
     62||OSGeo.SDF||OSGeo.SDF.5.0||
     63||OSGeo.SDF.3||OSGeo.SDF.3.2||
     64||OSGeo.SDF.4||OSGeo.SDF.4.0||
     65||OSGeo.SDF.3.1||OSGeo.SDF.3.1||
     66
     67The client decides how precise the search is by how many version parts are included in the requested provider name.
     68
     69In the above example, "OSGeo.SDF.5.0" is returned when "OSGeo.SDF" is requested. However, suppose that this provider is compatible with FDO version 5.0 and the version of FDO, used by the client, is 4.0. When there is a major version number difference then there is a good chance that the provider is binary incompatible with FDO, meaning that a crash or exception will occur when the provider is loaded.
     70
     71=== Config File Versions ===
     72
     73FDO provides the ability to serialize datastore contents to the FDO XML format. This includes feature schemas, spatial contexts, logical/physical mappings (Schema Overrides) and the features themselves.  FDO XML format data can be stored in a file. The FDO XML format can change between major FDO revisions so there are versioning issues surrounding these files. These are mainly compatibility issues that arise when a file is written by one version of FDO and read by another.
     74
     75In order for a particular version of FDO to determine if it can read a file, it needs to know what version of FDO created the file. Therefore, the file must contain this version information. The following sections discuss the versioning requirements for each type of serializable object.
     76
     77==== Feature Schemas ====
     78
     79Feature Schemas are currently written to XML without FDO version information. This version information needs to be added, going forward, in case the XML format for Feature Schemas changes in future. When a particular version of FDO reads a feature schema from a config file, it may need to know this version in order to read it properly.
     80
     81==== Spatial Contexts ====
     82
     83Similarly, Spatial Contexts are written to XML without FDO version information. This version information need to be added, going forward.
     84
     85==== Schema Overrides ====
     86
     87Schema Overrides are written to XML with FDO versioning information. The overrides include the name, major version and minor version of the provider that wrote them.
     88
     89The main requirement is to make sure that, when Schema Overrides are read from XML, they are parsed into objects that are binary compatible with the current FDO.
     90
     91When FDO reads a Schema Override Set from XML, it delegates the reading to the provider that wrote the overrides. Schema Overrides are provider-specific, so only the provider knows how to read or write them. Currently, FDO chooses the earliest version of the provider that is equal to or greater than the version of the Schema Override set. However, it is possible for the chosen provider to be binary-incompatible with the current FDO. This means that the provider may either fail to be instantiated or it may parse the Schema Overrides into objects not compatible with the current FDO.
     92
     93==== Features ====
     94
     95Features are written to XML without FDO version information. This version information needs to be added, going forward.
     96
     97== Specification ==
     98
     99The following describes the client-visible changes proposed by this design.
     100
     101=== FDO API ===
     102
     103==== FdoFeatureAccessManager::!GetFeatureDataObjectsVersion ====
     104
     105When this function is called it will return the version of the feature data objects specification that the currently loaded Feature Access Manager supports. The version number string has the form [!VersionMajor].[!VersionMinor].[!BuildMajor].[!BuildMinor].
     106
     107The function signature shall be:
     108
     109{{{
     110FDO_API static FdoString* GetFeatureDataObjectsVersion();
     111}}}
     112
     113==== FdoConnectionManager::!CreateConnection() ====
     114
     115When this function is passed a provider name without version part (e.g. "OSGeo.SDF" ), it returns a connection object from the latest registered version of that provider.
     116
     117With this proposal, the provider chosen will be the provider with the latest binary-compatible !FeatureDataObjects version.
     118
     119The connection object will be instantiated from the chosen provider. If there is no compatible registered provider then !CreateConnection will return NULL.
     120
     121For the above provider searches, the provider's !FeatureDataObjects version will be used instead of the provider version itself. The reason for this is that the !FeatureDataObjects version is the one that corresponds to the version of the FDO core.
     122
     123The provider search behaviour is unchanged when the requested provider name contains version parts. In this case, the latest provider matching these version parts is chosen. However, in these cases, the client assumes the risk that the returned connection object may be incompatible with the current FDO.
     124
     125It is expected that most clients will pass in a provider name without version parts, since they would usually be interested in retrieving a binary-compatible version of the requested provider.
     126
     127A provider is considered to be binary-compatible with the current FDO if the specified parts of the provider's !FeatureDataObjectsVersion match those of the current version of FDO. For example, if the !FeatureDataObjectsVersion has 2 parts, then these must match the 1st 2 parts of the current FDO's version. The following table provides some concrete examples:
     128
     129||'''Provider !FeatureDataObjectsVersion'''||'''Compatible Versions of FDO'''||'''Incompatible FDO Versions'''||
     130||3||3.0.0.0||2.0.0.0
     131||||3.1.0.0||4.0.0.0||
     132||||3.2.0.1||4.1.0.0||
     133||||||||
     134||3.0||3.0.0.0||2.0.0.0
     135||||3.0.1.0||3.1.0.0||
     136||||||3.2.0.0||
     137||||||||
     138||3.2||3.2.0.0||3.1.0.0
     139||||3.2.1.0||3.1.1.0||
     140||||||3.3.0.0||
     141||||||||
     142||3.1.0.1||3.1.0.1||3.1.0.0
     143||||||3.1.0.2||
     144||||||3.1.2||
     145
     146The 4th example is for illustration and would not likely happen in the real world. It is unlikely that versions as similar as 3.1.0.1 and 3.1.0.2 would be incompatible.
     147
     148==== !FdoProviderNameTokens ====
     149
     150This class will be modified to support the removing of version parts from a provider name.
     151
     152''!ToString (new)''
     153
     154This function converts this tokenize provider name back to a string:
     155
     156{{{
     157FdoStringP FdoProviderNameTokens::ToString( bool includeVersion = true )
     158}}}
     159
     160When includeVersion is true, the full provider name is returned. When includeVersion is false, the version parts are omitted from the returned name.
     161
     162For Example, the following removes the version parts from a provider name:
     163
     164{{{
     165FdoStringP srcName = L"OSGeo.SDF.3.1";
     166FdoStringP destName;
     167FdoProviderNameTokensP tokens = FdoProviderNameTokens::Create( srcName );
     168destName = tokens->ToString( false );
     169assert ( destName == L"OSGeo.SDF" );
     170}}}
     171
     172''!GetNameTokens (modified)''
     173
     174For consistency, the !GetNameTokens signature will change to the following:
     175
     176
     177{{{
     178FdoStringsP FdoProviderNameTokens::GetNameTokens( bool includeVersion = true )
     179}}}
     180
     181includeVersion is a new parameter. When false, the returned string collection will not include the version parts.
     182
     183For Example, the following removes the version parts from a provider name (note that a bit more work is required than in the above !ToString example):
     184
     185
     186{{{
     187FdoStringP srcName = L"Autodesk.Oracle.3.1";
     188FdoStringP destName;
     189FdoProviderNameTokensP tokens = FdoProviderNameTokens::Create( srcName );
     190GisStringsP nameTokens = tokens->GetNameTokens( false  );
     191destName = tokens->ToString( L"." );
     192assert ( destName == L"Autodesk.Oracle" );
     193}}}
     194
     195==== IProviderRegistry::!GetProviders (modified) ====
     196
     197!GetProviders will be enhanced to allow a client to determine if a particular provider is compatible with the current FDO:
     198
     199{{{
     200FdoProviderCollection* IProviderRegistry::GetProviders( bool compatibleOnly = false)
     201}}}
     202
     203compatibleOnly is a new parameter. When false, all registered providers are returned. When true, only providers compatible with the current FDO are returned.
     204
     205For Example, the following code checks to see if a particular provider is compatible with the currently running FDO:
     206
     207{{{
     208FdoPtr<IProviderRegistry> registry = FeatureAccessManager::GetProviderRegistry();
     209FdoString* providerName = L"OSGeo.SDF.3.1";
     210FdoPtr<FdoProviderCollection> providers = registry->GetProviders(true);
     211bool isCompatible = (providers->IndexOf(providerName) >= 0);
     212}}}
     213
     214==== FdoProvider::!GetIsCompatible (new) ====
     215
     216IProviderRegistry::!GetProviders implementations can use this function to test whether a particular provider is compatible. The signature is:
     217
     218{{{
     219bool FdoProvider::!GetIsCompatible()
     220}}}
     221
     222It returns true if this provider is compatible with the currently running FDO, and false otherwise.
     223
     224For Example, !GetIsCompatible is used to test the provider's compatibility:
     225
     226{{{
     227FdoPtr<IProviderRegistry> registry = FeatureAccessManager::GetProviderRegistry();
     228FdoString* providerName = L"OSGeo.SDF.3.1";
     229FdoPtr<FdoProviderCollection> providers = registry->GetProviders(false);
     230FdoInt32 ix = providers->IndexOf(providerName);
     231FdoPtr<FdoProvider> provider = providers->GetItem( ix );
     232bool isCompatible = provider->GetIsCompatible();
     233}}}
     234
     235==== FdoPhysicalSchemaMappingCollection::!ReadXml (modified) ====
     236
     237When this function encounters a Schema Override Set, it searches the provider registry for the earliest provider whose version is equal or greater than the Schema Override Set's version. It then invokes that provider to read the Schema Override Set.
     238
     239With this proposal, the latest provider that is binary-compatible with the current FDO will be chosen.
     240
     241It is possible that the chosen provider will be too old to read the given Schema Override Set. When the provider reads the Schema Override set, it may encounter a construct that it doesn't understand. If this happens, the action taken depends on the current !ErrorLevel passed to !ReadXml, via the flags parameter:
     242
     243High – an error is reported[[br]]
     244Other – the construct is ignored[[br]]
     245
     246=== Feature Schemas ===
     247
     248The fdo:version and fdo:minimumVersion elements will also be allowed on the <xs:schema> element. Both attributes are optional.
     249When the FDO XML Schema writer writes a single schema, it does not wrap the schema in an <fdo:Datastore> element. This is done to maximize compatibility with external applications. In this case, the document root element is <xs:schema>. Therefore, the schema writer will add the versioning attributes to the <xs:schema> element, in this case.
     250
     251In order to support the required schema override change, the !FdoFeatureSchema class will be modified to include a !GetFeatureDataObjectsVersion function as well as a !GetMinimumFeatureDataObjectsVersion function.
     252
     253
     254{{{
     255class FdoFeatureSchema :
     256    public FdoSchemaElement,
     257    public FdoXmlSerializable
     258{
     259public:
     260    /// \brief
     261    /// Gets the version of FDO that created the Feature Schema
     262    ///
     263    /// \return
     264    /// Returns the Feature Data Objects version as an FdoString.
     265    /// The FDO version must conform to the format:
     266    /// "[VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor]".
     267    ///
     268    FDO_API virtual FdoString* GetFeatureDataObjectsVersion();
     269
     270    /// \brief
     271    /// Gets the earliest version of FDO that can possibly
     272    /// read the Schema Mapping
     273    ///
     274    /// \return
     275    /// Returns the Feature Data Objects version as an FdoString.
     276    /// The FDO version must conform to the format:
     277    /// "[VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor]".
     278    ///
     279    FDO_API virtual FdoString* GetMinimumFeatureDataObjectsVersion();
     280
     281
     282};
     283}}}
     284
     285=== Schema Overrides ===
     286
     287The Schema Overrides version is already stored in the provider attribute of the <!SchemaMapping> tag. The following new attribute (for the <!SchemaMapping> tag ) will be defined:
     288
     289        minimumVersion
     290
     291Its behaviour is identical to that of the general fdo:minimumVersion.
     292
     293The following updated !FdoOverride.xsd definitions reflect the proposed changes above.
     294
     295
     296{{{
     297<xs:schema>
     298...
     299...
     300    <xs:complexType name="PhysicalSchemaMappingType" abstract="true">
     301        <xs:complexContent>
     302            <xs:extension base="SchemaMappingElement">
     303                <xs:attribute name="provider" type="ProviderType" use="required"/>
     304                <xs:attribute ref="fdo:minimumVersion" use="optional"/>
     305            </xs:extension>
     306        </xs:complexContent>
     307    </xs:complexType>
     308...
     309...
     310</xs:schema>
     311}}}
     312
     313
     314In order to support the required schema override change, the !FdoPhysicalSchemaMapping and !FdoXmlSchemaMapping classes will be modified to include a !GetMinimumProviderVersion function.
     315
     316
     317{{{
     318class FdoPhysicalSchemaMapping :
     319        public FdoPhysicalElementMapping,
     320        public FdoXmlSerializable
     321{
     322public:
     323    /// \brief
     324    /// Gets the earliest version of Provider that can possibly
     325    /// read the Schema Mapping
     326    ///
     327    /// \return
     328    /// Returns the version as a constant wchar_t*.
     329    /// The version must conform to the format:
     330    /// "[VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor]".
     331    ///
     332    FDO_API virtual FdoString* GetMinimumProviderVersion () = 0;
     333
     334
     335};
     336
     337/// \brief
     338/// FdoXmlSchemaMapping specifies overrides for translating a feature schema
     339/// between FDO and GML.
     340class FdoXmlSchemaMapping :
     341        public FdoPhysicalSchemaMapping
     342{
     343public:
     344    /// \brief
     345    /// Gets the earliest version of Provider that can possibly
     346    /// read the Schema Mapping
     347    ///
     348    /// \return
     349    /// Returns the version as a constant wchar_t*.
     350    /// The version must conform to the format:
     351    /// "[VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor]".
     352    ///
     353    FDO_API FdoString* GetMinimumProviderVersion ();
     354
     355
     356};
     357}}}
     358
     359=== Managed API ===
     360
     361Here are the Managed API wrapper definitions for the Unmanaged API described above.
     362
     363
     364{{{
     365/// \brief
     366/// The FeatureAccessManager class manages a registry of feature
     367/// providers stored in the registry and provides support for
     368/// dynamic discovery and binding to registered feature providers
     369public __sealed __gc class FeatureAccessManager
     370{
     371public:
     372
     373
     374    /// \brief
     375    /// Gets the version of the feature data objects
     376    /// specification the Feature Access Manager conforms to.
     377    /// The version number string has the form
     378    /// [VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor].
     379    ///
     380    /// \return
     381    /// Returns the Feature Data Objects version as a constant wchar_t*.
     382    ///
     383    static System::String* GetFeatureDataObjectsVersion();
     384
     385
     386};
     387
     388/// \brief
     389/// A provider name tokenized into its company, name and version parts.
     390public __gc class ProviderNameTokens : public Disposable
     391{
     392public:
     393
     394
     395    /// \brief
     396    /// Gets all of the tokens in this provider name
     397    ///
     398    /// \return
     399    /// Returns the collection of tokens.
     400    ///   Element 0 is the company
     401    ///   Element 1 is the unqualified name
     402    ///   the rest of the elements are the individual
     403    /// parts of the version number.
     404    ///
     405    System::String* GetNameTokens()[];
     406
     407    /// \brief
     408    /// Gets all of the tokens in this provider name
     409    ///
     410    /// \param includeVersion
     411    /// Input a boolean flag indicating that the version information
     412    /// should be returned as a part of the provider name. When
     413    /// includeVersion is true, the full provider name is returned.
     414    /// When includeVersion is false, the version parts are omitted
     415    /// from the returned name.
     416    ///
     417    /// \return
     418    /// Returns the collection of tokens.
     419    ///   Element 0 is the company
     420    ///   Element 1 is the unqualified name
     421    ///   the rest of the elements are the individual
     422    /// parts of the version number.
     423    ///
     424    System::String* GetNameTokens( Boolean includeVersion)[];
     425
     426    /// \brief
     427    /// Converts the tokenized provider name back to a string.
     428    ///
     429    /// \param includeVersion
     430    /// Input a boolean flag indicating that the version information
     431    /// should be returned as a part of the provider name. When
     432    /// includeVersion is true, the full provider name is returned.
     433    /// When includeVersion is false, the version parts are omitted
     434    /// from the returned name.
     435    ///
     436    /// \return
     437    /// Returns the tokenized provider name.
     438    ///
     439    System::String* ToString( Boolean includeVersion );
     440
     441
     442};
     443
     444/// \brief
     445/// The IProviderRegistry interface supports registering,
     446/// un-registering, and enumerating registered feature providers.
     447/// \note
     448/// This is not the Windows registry.
     449public __gc __interface IProviderRegistry : public System::IDisposable
     450{
     451public:
     452
     453
     454
     455    /// \brief
     456    /// Gets a read only collection of information describing
     457    /// each of the registered feature providers.
     458    ///
     459    /// \return
     460    /// Returns an an instance of ProviderCollection.
     461    ProviderCollection* GetProviders();
     462
     463    /// \brief
     464    /// Gets a read only collection of information describing
     465    /// each of the registered feature providers.
     466    ///
     467    /// \param compatibleOnly
     468    /// When false, all registered providers are returned.
     469    /// When true, only providers compatible with the current FDO are returned.
     470    ///
     471    /// \return
     472    /// Returns an an instance of ProviderCollection.
     473    ProviderCollection* GetProviders( Boolean compatibleOnly );
     474
     475
     476};
     477
     478/// \brief
     479/// ProviderRegistry supports registering, un-registering, and
     480/// enumerating registered feature providers.
     481/// \note
     482/// This is not the Windows registry.
     483public __gc class ProviderRegistry :
     484public Disposable,
     485public IProviderRegistry
     486{
     487public:
     488
     489
     490
     491    /// \brief
     492    /// Gets a read only collection of information describing
     493    /// each of the registered feature providers.
     494    ///
     495    /// \return
     496    /// Returns an an instance of ProviderCollection.
     497    ProviderCollection* GetProviders();
     498
     499    /// \brief
     500    /// Gets a read only collection of information describing
     501    /// each of the registered feature providers.
     502    ///
     503    /// \param compatibleOnly
     504    /// When false, all registered providers are returned.
     505    /// When true, only providers compatible with the current FDO are returned.
     506    ///
     507    /// \return
     508    /// Returns an an instance of ProviderCollection.
     509    ProviderCollection* GetProviders ( Boolean compatibleOnly );
     510
     511
     512};
     513
     514/// \brief
     515/// Provides information about a feature provider, including name, description,
     516/// library, and version information.
     517public __sealed __gc class Provider : public Disposable
     518{
     519public:
     520
     521
     522    /// \brief
     523    /// Gets a boolean flag indicating if the provider is compatible with the
     524    /// currently running version of FDO.
     525    ///
     526    /// \return
     527    /// Returns returns true if this provider is compatible with the currently
     528    /// running FDO, and false otherwise.
     529    ///
     530    __property System::Boolean get_IsCompatible();
     531 …
     532 …
     533};
     534
     535/// \brief
     536/// The FdoFeatureSchema class derives from FdoSchemaElement.
     537/// A feature schema contains all of the classes and relationships
     538/// that make up a particular data model. The FdoFeatureSchema class
     539/// can be used to either create a new schema or to browse the schema end of a
     540/// connection. In the later case, the FdoFeatureSchema instance is created by
     541/// the DescribeSchema command. In this case the schema objects have
     542/// additional properties, such as coordinate system definitions that
     543/// can be useful to the
     544/// application when placed in context with the schema objects.
     545public __gc class FeatureSchema :
     546public SchemaElement,
     547public IXmlSerializable
     548{
     549public:
     550
     551
     552    /// \brief
     553    /// Gets the version of FDO that created the Feature Schema
     554    ///
     555    /// \return
     556    /// Returns the Feature Data Objects version as an FdoString.
     557    /// The FDO version must conform to the format:
     558    /// "[VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor]".
     559    ///
     560    __property System::String* get_FeatureDataObjectsVersion ();
     561
     562    /// \brief
     563    /// Gets the earliest version of FDO that can possibly
     564    /// read the Schema Mapping
     565    ///
     566    /// \return
     567    /// Returns the Feature Data Objects version as an FdoString.
     568    /// The FDO version must conform to the format:
     569    /// "[VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor]".
     570    ///
     571    __property System::String* get_MinimumFeatureDataObjectsVersion ();
     572
     573
     574};
     575
     576
     577/// \brief
     578/// PhysicalSchemaMapping is the base class of all Schema Override sets.
     579/// Each instance contains the overrides for a particular Feature Schema
     580/// and FDO Provider. Each FDO Provider, that allows Schema Overrides, must
     581/// create a sub-class of this class. This sub-class must implement the
     582/// overrides that are specific to the provider. The Provider can also add
     583/// support, for serializing to an XML document, by overriding the functions
     584/// inherited from  FdoXmlSerializable.
     585public __gc class PhysicalSchemaMapping : public PhysicalElementMapping
     586{
     587public:
     588
     589
     590    /// \brief
     591    /// Gets the earliest version of the Provider that can
     592    /// possibly read the Schema Mapping
     593    ///
     594    /// \return
     595    /// Returns the Provider version as an FdoString.
     596    /// The version must conform to the format:
     597    /// "[VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor]".
     598    ///
     599    __property System::String* get_MinimumProviderVersion();
     600
     601
     602};
     603
     604
     605/// \brief
     606/// FdoXmlSchemaMapping specifies overrides for translating
     607/// a feature schema between FDO and GML.
     608public __gc class XmlSchemaMapping : public PhysicalSchemaMapping
     609{
     610public:
     611
     612
     613
     614    /// \brief
     615    /// Gets the earliest version of the Provider that can possibly
     616    /// read the Schema Mapping
     617    ///
     618    /// \return
     619    /// Returns the Provider version as an FdoString.
     620    /// The version must conform to the format:
     621    /// "[VersionMajor].[VersionMinor].[BuildMajor].[BuildMinor]".
     622    ///
     623    __property System::String* get_MinimumProviderVersion();
     624
     625
     626};
     627}}}
     628
     629
     630
    28631
    29632== Test Plan ==