@@ -204,6 +204,11 @@ public bool IsDirty(string name) {
204204 /// overwritten to accept whatever value is submitted. This can be used, for instance, to prevent an update from being
205205 /// persisted to the data store on <see cref="Repositories.ITopicRepository.Save(Topic, Boolean, Boolean)"/>.
206206 /// </param>
207+ /// <param name="version">
208+ /// The <see cref="DateTime"/> value that the attribute was last modified. This is intended exclusively for use when
209+ /// populating the topic graph from a persistent data store as a means of indicating the current version for each
210+ /// attribute. This is used when e.g. importing values to determine if the existing value is newer than the source value.
211+ /// </param>
207212 /// <requires
208213 /// description="The key must be specified for the AttributeValue key/value pair."
209214 /// exception="T:System.ArgumentNullException">
@@ -219,7 +224,8 @@ public bool IsDirty(string name) {
219224 /// exception="T:System.ArgumentException">
220225 /// !value.Contains(" ")
221226 /// </requires>
222- public void SetValue ( string key , string ? value , bool ? isDirty = null ) => SetValue ( key , value , isDirty , true ) ;
227+ public void SetValue ( string key , string ? value , bool ? isDirty = null , DateTime ? version = null )
228+ => SetValue ( key , value , isDirty , true , version ) ;
223229
224230 /// <summary>
225231 /// Protected helper method that either adds a new <see cref="AttributeValue"/> object or updates the value of an existing
@@ -242,6 +248,11 @@ public bool IsDirty(string name) {
242248 /// Instructs the underlying code to call corresponding properties, if available, to ensure business logic is enforced.
243249 /// This should be set to false if setting attributes from internal properties in order to avoid an infinite loop.
244250 /// </param>
251+ /// <param name="version">
252+ /// The <see cref="DateTime"/> value that the attribute was last modified. This is intended exclusively for use when
253+ /// populating the topic graph from a persistent data store as a means of indicating the current version for each
254+ /// attribute. This is used when e.g. importing values to determine if the existing value is newer than the source value.
255+ /// </param>
245256 /// <requires
246257 /// description="The key must be specified for the AttributeValue key/value pair."
247258 /// exception="T:System.ArgumentNullException">
@@ -257,7 +268,7 @@ public bool IsDirty(string name) {
257268 /// exception="T:System.ArgumentException">
258269 /// !value.Contains(" ")
259270 /// </requires>
260- internal void SetValue ( string key , string ? value , bool ? isDirty , bool enforceBusinessLogic ) {
271+ internal void SetValue ( string key , string ? value , bool ? isDirty , bool enforceBusinessLogic , DateTime ? version = null ) {
261272
262273 /*------------------------------------------------------------------------------------------------------------------------
263274 | Validate input
@@ -292,15 +303,15 @@ internal void SetValue(string key, string? value, bool? isDirty, bool enforceBus
292303 else if ( originalAttribute . Value != value ) {
293304 markAsDirty = true ;
294305 }
295- var newAttribute = new AttributeValue ( key , value , markAsDirty , enforceBusinessLogic ) ;
306+ var newAttribute = new AttributeValue ( key , value , markAsDirty , enforceBusinessLogic , version ) ;
296307 this [ IndexOf ( originalAttribute ) ] = newAttribute ;
297308 }
298309
299310 /*------------------------------------------------------------------------------------------------------------------------
300311 | Create new attribute value
301312 \-----------------------------------------------------------------------------------------------------------------------*/
302313 else {
303- Add ( new AttributeValue ( key , value , isDirty ?? true , enforceBusinessLogic ) ) ;
314+ Add ( new AttributeValue ( key , value , isDirty ?? true , enforceBusinessLogic , version ) ) ;
304315 }
305316
306317 }
@@ -316,8 +327,8 @@ internal void SetValue(string key, string? value, bool? isDirty, bool enforceBus
316327 /// <para>
317328 /// If a settable property is available corresponding to the <see cref="AttributeValue.Key"/>, the call should be routed
318329 /// through that to ensure local business logic is enforced. This is determined by looking for the "__" prefix, which is
319- /// set by the <see cref="SetValue(String, String, Boolean?, Boolean)"/>'s enforceBusinessLogic parameter. To avoid an
320- /// infinite loop, internal setters _must_ call this overload.
330+ /// set by the <see cref="SetValue(String, String, Boolean?, Boolean, DateTime? )"/>'s enforceBusinessLogic parameter. To
331+ /// avoid an infinite loop, internal setters _must_ call this overload.
321332 /// </para>
322333 /// <para>
323334 /// Compared to the base implementation, will throw a specific <see cref="ArgumentException"/> error if a duplicate key
@@ -357,8 +368,8 @@ protected override void InsertItem(int index, AttributeValue item) {
357368 /// <remarks>
358369 /// If a settable property is available corresponding to the <see cref="AttributeValue.Key"/>, the call should be routed
359370 /// through that to ensure local business logic is enforced. This is determined by looking for the "__" prefix, which is
360- /// set by the <see cref="SetValue(String, String, Boolean?, Boolean)"/>'s enforceBusinessLogic parameter. To avoid an
361- /// infinite loop, internal setters _must_ call this overload.
371+ /// set by the <see cref="SetValue(String, String, Boolean?, Boolean, DateTime? )"/>'s enforceBusinessLogic parameter. To
372+ /// avoid an infinite loop, internal setters _must_ call this overload.
362373 /// </remarks>
363374 /// <param name="index">The location that the <see cref="AttributeValue"/> should be set.</param>
364375 /// <param name="item">The <see cref="AttributeValue"/> object which is being inserted.</param>
@@ -379,8 +390,8 @@ protected override void SetItem(int index, AttributeValue item) {
379390 /// <remarks>
380391 /// If a settable property is available corresponding to the <see cref="AttributeValue.Key"/>, the call should be routed
381392 /// through that to ensure local business logic is enforced. This is determined by looking for the "__" prefix, which is
382- /// set by the <see cref="SetValue(String, String, Boolean?, Boolean)"/>'s enforceBusinessLogic parameter. To avoid an
383- /// infinite loop, internal setters _must_ call this overload.
393+ /// set by the <see cref="SetValue(String, String, Boolean?, Boolean, DateTime? )"/>'s enforceBusinessLogic parameter. To
394+ /// avoid an infinite loop, internal setters _must_ call this overload.
384395 /// </remarks>
385396 /// <param name="originalAttribute">The <see cref="AttributeValue"/> object which is being inserted.</param>
386397 /// <param name="settableAttribute">
@@ -403,6 +414,7 @@ private bool EnforceBusinessLogic(AttributeValue originalAttribute, out Attribut
403414 }
404415 _typeCache . SetPropertyValue ( _associatedTopic , originalAttribute . Key , originalAttribute . Value ) ;
405416 this [ originalAttribute . Key ] . IsDirty = originalAttribute . IsDirty ;
417+ this [ originalAttribute . Key ] . LastModified = originalAttribute . LastModified ;
406418 _setCounter = 0 ;
407419 return false ;
408420 }
0 commit comments