Skip to content

Commit

Permalink
📝 doc comments for ValueGeneration.*
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanmiller committed Oct 30, 2015
1 parent fb4cad0 commit 5a9820a
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 3 deletions.
12 changes: 12 additions & 0 deletions src/EntityFramework.Core/ValueGeneration/GuidValueGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,22 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// Generates <see cref="Guid"/> values using <see cref="Guid.NewGuid()"/>.
/// The generated values are non-temporary, meaning they will be saved to the database.
/// </summary>
public class GuidValueGenerator : ValueGenerator<Guid>
{
/// <summary>
/// Gets a value to be assigned to a property.
/// </summary>
/// <returns> The value to be assigned to a property. </returns>
public override Guid Next() => Guid.NewGuid();

/// <summary>
/// Gets a value indicating whether the values generated are temporary or permanent. This implementation
/// always returns false, meaning the generated values will be saved to the database.
/// </summary>
public override bool GeneratesTemporaryValues => false;
}
}
26 changes: 23 additions & 3 deletions src/EntityFramework.Core/ValueGeneration/HiLoValueGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,43 @@
namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// Acts as a <see cref="ValueGenerator" /> by requesting a block of values from the
/// underlying database and returning them one by one. Will ask the underlying
/// database for another block when the current block is exhausted.
/// <para>
/// Acts as a <see cref="ValueGenerator" /> by requesting a block of values from the
/// underlying database and returning them one by one. Will ask the underlying
/// database for another block when the current block is exhausted.
/// </para>
/// <para>
/// A block is represented by a low value fetched from the database, and then a block size
/// that indicates how many sequential values can be used, starting from the low value, before
/// a new low value must be fetched from the database.
/// </para>
/// </summary>
/// <typeparam name="TValue"> The type of values that are generated. </typeparam>
public abstract class HiLoValueGenerator<TValue> : ValueGenerator<TValue>
{
private readonly HiLoValueGeneratorState _generatorState;

/// <summary>
/// Initializes a new instance of the <see cref="HiLoValueGenerator{TValue}"/> class.
/// </summary>
/// <param name="generatorState"> The state used to keep track of which value to return next. </param>
protected HiLoValueGenerator([NotNull] HiLoValueGeneratorState generatorState)
{
Check.NotNull(generatorState, nameof(generatorState));

_generatorState = generatorState;
}

/// <summary>
/// Gets a value to be assigned to a property.
/// </summary>
/// <returns> The value to be assigned to a property. </returns>
public override TValue Next() => _generatorState.Next<TValue>(GetNewLowValue);

/// <summary>
/// Gets the low value for the next block of values to be used.
/// </summary>
/// <returns> The low value for the next block of values to be used. </returns>
protected abstract long GetNewLowValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// The thread safe state used by <see cref="HiLoValueGenerator{TValue}"/>.
/// </summary>
public class HiLoValueGeneratorState
{
private readonly object _lock;
private HiLoValue _currentValue;
private readonly int _blockSize;

/// <summary>
/// Initializes a new instance of the <see cref="HiLoValueGeneratorState"/> class.
/// </summary>
/// <param name="blockSize">
/// The number of sequential values that can be used, starting from the low value, before
/// a new low value must be fetched from the database.
/// </param>
public HiLoValueGeneratorState(int blockSize)
{
if (blockSize <= 0)
Expand All @@ -27,6 +37,14 @@ public HiLoValueGeneratorState(int blockSize)
_lock = new object();
}

/// <summary>
/// Gets a value to be assigned to a property.
/// </summary>
/// <typeparam name="TValue"> The type of values being generated. </typeparam>
/// <param name="getNewLowValue">
/// A function to get the next low value if needed.
/// </param>
/// <returns> The value to be assigned to a property. </returns>
public virtual TValue Next<TValue>([NotNull] Func<long> getNewLowValue)
{
Check.NotNull(getNewLowValue, nameof(getNewLowValue));
Expand Down
20 changes: 20 additions & 0 deletions src/EntityFramework.Core/ValueGeneration/IValueGeneratorCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,28 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// <para>
/// Keeps a cache of value generators for properties.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
public interface IValueGeneratorCache
{
/// <summary>
/// Gets the existing value generator from the cache, or creates a new one if one is not present in
/// the cache.
/// </summary>
/// <param name="property"> The property to get the value generator for. </param>
/// <param name="entityType">
/// The entity type that the value generator will be used for. When called on inherited properties on derived entity types,
/// this entity type may be different from the declared entity type on <paramref name="property" />
/// </param>
/// <param name="factory"> Factory to create a new value generator if one is not present in the cache. </param>
/// <returns> The existing or newly created value generator. </returns>
ValueGenerator GetOrAdd(
[NotNull] IProperty property,
[NotNull] IEntityType entityType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,26 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// <para>
/// Selects value generators to be used to generate values for properties of entities.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
public interface IValueGeneratorSelector
{
/// <summary>
/// Selects the appropriate value generator for a given property.
/// </summary>
/// <param name="property"> The property to get the value generator for. </param>
/// <param name="entityType">
/// The entity type that the value generator will be used for. When called on inherited properties on derived entity types,
/// this entity type may be different from the declared entity type on <paramref name="property" />
/// </param>
/// <returns> The value generator to be used. </returns>
ValueGenerator Select([NotNull] IProperty property, [NotNull] IEntityType entityType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,20 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// Generates sequential <see cref="Guid"/> values using the same algorithm as NEWSEQUENTIALID()
/// in Microsoft SQL Server. This is useful when entities are being saved to a database where sequential
/// GUIDs will provide a performance benefit. The generated values are non-temporary, meaning they will
/// be saved to the database.
/// </summary>
public class SequentialGuidValueGenerator : ValueGenerator<Guid>
{
private long _counter = DateTime.UtcNow.Ticks;

/// <summary>
/// Gets a value to be assigned to a property.
/// </summary>
/// <returns> The value to be assigned to a property. </returns>
public override Guid Next()
{
var guidBytes = Guid.NewGuid().ToByteArray();
Expand All @@ -32,6 +42,10 @@ public override Guid Next()
return new Guid(guidBytes);
}

/// <summary>
/// Gets a value indicating whether the values generated are temporary or permanent. This implementation
/// always returns false, meaning the generated values will be saved to the database.
/// </summary>
public override bool GeneratesTemporaryValues => false;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// Generates <see cref="Guid"/> values using <see cref="Guid.NewGuid()"/>.
/// The generated values are temporary, meaning they will be replaced by database
/// generated values when the entity is saved.
/// </summary>
public class TemporaryGuidValueGenerator : GuidValueGenerator
{
/// <summary>
/// Gets a value indicating whether the values generated are temporary or permanent. This implementation
/// always returns true, meaning the generated values will be replaced by database generated values when
/// the entity is saved
/// </summary>
public override bool GeneratesTemporaryValues => true;
}
}
26 changes: 26 additions & 0 deletions src/EntityFramework.Core/ValueGeneration/ValueGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// Generates values for properties when an entity is added to a context.
/// </summary>
public abstract class ValueGenerator
{
/// <summary>
/// Gets a value to be assigned to a property.
/// </summary>
/// <returns> The value to be assigned to a property. </returns>
public virtual object Next() => NextValue();

/// <summary>
/// Template method to be overridden by implementations to perform value generation.
/// </summary>
/// <returns> The generated value. </returns>
protected abstract object NextValue();

/// <summary>
/// <para>
/// Gets a value indicating whether the values generated are temporary (i.e they should be replaced
/// by database generated values when the entity is saved) or are permanent (i.e. the generated values
/// should be saved to the database).
/// </para>
/// <para>
/// An example of temporary value generation is generating negative numbers for an integer primary key
/// that are then replaced by positive numbers generated by the database when the entity is saved. An
/// example of permanent value generation are client-generated values for a <see cref="Guid"/> primary
/// key which are saved to the database.
/// </para>
/// </summary>
public abstract bool GeneratesTemporaryValues { get; }
}
}
20 changes: 20 additions & 0 deletions src/EntityFramework.Core/ValueGeneration/ValueGeneratorCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// <para>
/// Keeps a cache of value generators for properties.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
public abstract class ValueGeneratorCache : IValueGeneratorCache
{
private readonly ConcurrentDictionary<CacheKey, ValueGenerator> _cache
Expand Down Expand Up @@ -49,6 +58,17 @@ public override int GetHashCode()
}
}

/// <summary>
/// Gets the existing value generator from the cache, or creates a new one if one is not present in
/// the cache.
/// </summary>
/// <param name="property"> The property to get the value generator for. </param>
/// <param name="entityType">
/// The entity type that the value generator will be used for. When called on inherited properties on derived entity types,
/// this entity type may be different from the declared entity type on <paramref name="property" />
/// </param>
/// <param name="factory"> Factory to create a new value generator if one is not present in the cache. </param>
/// <returns> The existing or newly created value generator. </returns>
public virtual ValueGenerator GetOrAdd(
IProperty property, IEntityType entityType, Func<IProperty, IEntityType, ValueGenerator> factory)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// Base class for factories that create value generators.
/// </summary>
public abstract class ValueGeneratorFactory
{
/// <summary>
/// Creates a new value generator.
/// </summary>
/// <param name="property"> The property to create the value generator for. </param>
/// <returns> The newly created value generator. </returns>
public abstract ValueGenerator Create([NotNull] IProperty property);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// Factory to create value generators of type <typeparam name="TValueGenerator" />.
/// </summary>
public class ValueGeneratorFactory<TValueGenerator> : ValueGeneratorFactory
where TValueGenerator : ValueGenerator, new()
{
/// <summary>
/// Creates a new value generator.
/// </summary>
/// <param name="property"> The property to create the value generator for. </param>
/// <returns> The newly created value generator. </returns>
public override ValueGenerator Create(IProperty property)
{
Check.NotNull(property, nameof(property));
Expand Down
34 changes: 34 additions & 0 deletions src/EntityFramework.Core/ValueGeneration/ValueGeneratorSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@

namespace Microsoft.Data.Entity.ValueGeneration
{
/// <summary>
/// <para>
/// Selects value generators to be used to generate values for properties of entities.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
public class ValueGeneratorSelector : IValueGeneratorSelector
{
private readonly ValueGeneratorFactory<GuidValueGenerator> _guidFactory
Expand All @@ -31,15 +40,31 @@ private readonly ValueGeneratorFactory<TemporaryDateTimeValueGenerator> _dateTim
private readonly ValueGeneratorFactory<TemporaryDateTimeOffsetValueGenerator> _dateTimeOffsetFactory
= new ValueGeneratorFactory<TemporaryDateTimeOffsetValueGenerator>();

/// <summary>
/// The cache being used to store value generator instances.
/// </summary>
public virtual IValueGeneratorCache Cache { get; }

/// <summary>
/// Initializes a new instance of the <see cref="ValueGeneratorSelector"/> class.
/// </summary>
/// <param name="cache"> The cache to be used to store value generator instances. </param>
public ValueGeneratorSelector([NotNull] IValueGeneratorCache cache)
{
Check.NotNull(cache, nameof(cache));

Cache = cache;
}

/// <summary>
/// Selects the appropriate value generator for a given property.
/// </summary>
/// <param name="property"> The property to get the value generator for. </param>
/// <param name="entityType">
/// The entity type that the value generator will be used for. When called on inherited properties on derived entity types,
/// this entity type may be different from the declared entity type on <paramref name="property" />
/// </param>
/// <returns> The value generator to be used. </returns>
public virtual ValueGenerator Select(IProperty property, IEntityType entityType)
{
Check.NotNull(property, nameof(property));
Expand All @@ -48,6 +73,15 @@ public virtual ValueGenerator Select(IProperty property, IEntityType entityType)
return Cache.GetOrAdd(property, entityType, Create);
}

/// <summary>
/// Creates a new value generator for the given property.
/// </summary>
/// <param name="property"> The property to get the value generator for. </param>
/// <param name="entityType">
/// The entity type that the value generator will be used for. When called on inherited properties on derived entity types,
/// this entity type may be different from the declared entity type on <paramref name="property" />
/// </param>
/// <returns> The newly created value generator. </returns>
public virtual ValueGenerator Create([NotNull] IProperty property, [NotNull] IEntityType entityType)
{
Check.NotNull(property, nameof(property));
Expand Down
Loading

0 comments on commit 5a9820a

Please sign in to comment.