Skip to content

Commit

Permalink
Release 1.0.29-beta:
Browse files Browse the repository at this point in the history
In vm.Aspects.Model:
* Fixed a bug in HiLoIdentityGenerator where the generated long ID-s would not go above int.MaxValue.
* Made all repositpory tests to work with both HiLo and SQL identity providers.
* Added new method IOrmSpecifics.GetEntitySetName. Implemented for EFRepositoryBase and for MapObjectsRepository.
  • Loading branch information
vmelamed committed Jan 16, 2016
1 parent 0db9739 commit 39efd6c
Show file tree
Hide file tree
Showing 29 changed files with 615 additions and 353 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>AspectExpressionSerialization</id>
<version>1.0.28</version>
<version>1.0.29</version>
<authors>Val Melamed</authors>
<owners>Val Melamed</owners>
<summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
[assembly: AssemblyTitle("vm.Aspects.Linq.Expressions.Serialization")]
[assembly: AssemblyDescription("Serializes and deserializes LINQ expression trees to and from XML documents.")]

[assembly: AssemblyVersion("1.0.28")]
[assembly: AssemblyFileVersion("1.0.28")]
[assembly: AssemblyInformationalVersion("1.0.28")]
[assembly: AssemblyVersion("1.0.29")]
[assembly: AssemblyFileVersion("1.0.29")]
[assembly: AssemblyInformationalVersion("1.0.29")]

[assembly: InternalsVisibleTo(
"vm.Aspects.Linq.Expressions.Serialization.Test, " +
Expand Down
13 changes: 13 additions & 0 deletions Aspects/Model/EFRepository/EFSpecifics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ public Type GetEntityType(
return ObjectContext.GetObjectType(reference.GetType());
}

/// <summary>
/// Gets the name of the entity set associated with the specified type.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="repository">The repository.</param>
/// <returns>System.String.</returns>
public string GetEntitySetName(
Type type,
IRepository repository)
{
return (repository as EFRepositoryBase).ObjectContext.GetEntitySetName(type);
}

/// <summary>
/// Determines whether the specified reference is a reference to an ORM generated wrapper/proxy of the actual object instead of the actual object itself.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
using vm.Aspects.Diagnostics;
using vm.Aspects.Validation;

namespace vm.Aspects.Model.EFRepository.HiLoIdentity
{
abstract class HiLoIdentityGeneratorMetadata
{
[Dump(0)]
[StringLengthValidator(HiLoIdentityGenerator.EntitySetNameMaxLength)]
[RegexValidator(RegularExpression.RexCSharpIdentifier)]
public object EntitySetName { get; set; }

[Dump(1)]
[NonnegativeValidator]
public object HighValue { get; set; }

[Dump(2)]
[NonnegativeValidator]
public object LowValue { get; set; }

[Dump(3)]
[NonnegativeValidator]
public object MaxLowValue { get; set; }

[Dump(4)]
public object HasIdentity { get; set; }
}
}
58 changes: 33 additions & 25 deletions Aspects/Model/EFRepository/HiLoIdentity/HiLoIdentityGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

namespace vm.Aspects.Model.EFRepository.HiLoIdentity
{
/// <summary>
/// Class HiLoIdentityGenerator. Implements the Hi-Lo algorithm for generating unique ID-s.
/// </summary>
public class HiLoIdentityGenerator : BaseDomainEntity, IEquatable<HiLoIdentityGenerator>
[MetadataType(typeof(HiLoIdentityGeneratorMetadata))]
public partial class HiLoIdentityGenerator : BaseDomainEntity, IEquatable<HiLoIdentityGenerator>
{
#region Constants
/// <summary>
Expand All @@ -27,29 +29,38 @@ public class HiLoIdentityGenerator : BaseDomainEntity, IEquatable<HiLoIdentityGe
#endif
#endregion

/// <summary>
/// The maximum high value beyond which ID-s cannot be generated.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
public long MaxHighValue { get; }

#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="HiLoIdentityGenerator"/> class.
/// </summary>
public HiLoIdentityGenerator(int maxLowValue = DefaultMaxLowValue)
public HiLoIdentityGenerator()
: this(null, DefaultMaxLowValue)
{
MaxLowValue = DefaultMaxLowValue;
}

/// <summary>
/// Initializes a new instance of the <see cref="HiLoIdentityGenerator"/> class.
/// Initializes a new instance of the <see cref="HiLoIdentityGenerator" /> class.
/// </summary>
/// <param name="entitySetName">Name of the entity set.</param>
/// <param name="maxLowValue">The max low value.</param>
/// <param name="initialHighValue">The initial high value.</param>
public HiLoIdentityGenerator(
string entitySetName,
int maxLowValue = DefaultMaxLowValue)
int maxLowValue = DefaultMaxLowValue,
long initialHighValue = 1)
{
if (string.IsNullOrWhiteSpace(entitySetName))
throw new ArgumentNullException("entitySetName");
Contract.Requires<ArgumentException>(entitySetName==null || RegularExpression.CSharpIdentifier.IsMatch(entitySetName));

EntitySetName = entitySetName;
MaxLowValue = maxLowValue;
HighValue = initialHighValue;
MaxHighValue = long.MaxValue/MaxLowValue;
}
#endregion

Expand All @@ -60,24 +71,22 @@ public HiLoIdentityGenerator(
/// <value>
/// The name of the entities set.
/// </value>
[StringLengthValidator(EntitySetNameMaxLength)]
[RegexValidator(@"^[_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Mc}\p{Cf}\p{Pc}\p{Lm}][_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Nl}\p{Mc}\p{Cf}\p{Pc}\p{Lm}]*$")]
public string EntitySetName { get; protected internal set; }
public string EntitySetName { get; set; }

/// <summary>
/// Gets the next value of the high value.
/// </summary>
public int HighValue { get; protected internal set; }
public long HighValue { get; set; }

/// <summary>
/// Gets the low value.
/// </summary>
public int LowValue { get; protected internal set; }
public int LowValue { get; set; }

/// <summary>
/// Gets the maximum value of the low value.
/// </summary>
public int MaxLowValue { get; protected internal set; }
public int MaxLowValue { get; set; }
#endregion

/// <summary>
Expand All @@ -97,11 +106,11 @@ internal void IncrementHighValue()
{
unchecked
{
if (HighValue+1 == 0L)
if (HighValue+1 >= MaxHighValue)
throw new InvalidOperationException(
string.Format(
CultureInfo.InvariantCulture,
"Fatal error: the HighValue of the ID generator for entity set {0} has reached the maximum value.",
"FATAL ERROR: the HighValue of the ID generator for entity set {0} has reached the maximum value.",
EntitySetName));

HighValue++;
Expand All @@ -116,14 +125,13 @@ internal void IncrementHighValue()
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "n/a")]
public long GetId()
{
if (HighValue < 1L || LowValue >= MaxLowValue)
if (HighValue <= 1L || LowValue >= MaxLowValue)
return -1L;

return unchecked(((long)(HighValue-1) * MaxLowValue) + ++LowValue);
return unchecked((HighValue-1)*MaxLowValue + ++LowValue);
}
#endregion


#region Identity rules implementation.
#region IEquatable<HiLoIdentityGenerator> Members
/// <summary>
Expand All @@ -133,9 +141,9 @@ public long GetId()
/// <returns>
/// <list type="number">
/// <item><see langword="false"/> if <paramref name="other"/> is equal to <see langword="null"/>, otherwise</item>
/// <item><see langword="true"/> if <paramref name="other"/> refers to <c>this</c> object, otherwise</item>
/// <item><see langword="true"/> if <paramref name="other"/> refers to <c>this</c> object, otherwise</item>
/// <item><see langword="false"/> if <paramref name="other"/> is not the same type as <c>this</c> object, otherwise</item>
/// <item><see langword="true"/> if the current object and the <paramref name="other"/> are considered to be equal,
/// <item><see langword="true"/> if the current object and the <paramref name="other"/> are considered to be equal,
/// e.g. their business identities are equal; otherwise, <see langword="false"/>.</item>
/// </list>
/// </returns>
Expand Down Expand Up @@ -165,9 +173,9 @@ public virtual bool Equals(HiLoIdentityGenerator other)
/// <list type="number">
/// <item><see langword="false"/> if <paramref name="obj"/> cannot be cast to <see cref="HiLoIdentityGenerator"/>, otherwise</item>
/// <item><see langword="false"/> if <paramref name="obj"/> is equal to <see langword="null"/>, otherwise</item>
/// <item><see langword="true"/> if <paramref name="obj"/> refers to <c>this</c> object, otherwise</item>
/// <item><see langword="true"/> if <paramref name="obj"/> refers to <c>this</c> object, otherwise</item>
/// <item><see langword="false"/> if <paramref name="obj"/> is not the same type as <c>this</c> object, otherwise</item>
/// <item><see langword="true"/> if the current object and the <paramref name="obj"/> are considered to be equal,
/// <item><see langword="true"/> if the current object and the <paramref name="obj"/> are considered to be equal,
/// e.g. their business identities are equal; otherwise, <see langword="false"/>.</item>
/// </list>
/// </returns>
Expand Down Expand Up @@ -220,8 +228,8 @@ public override int GetHashCode()
/// <param name="other">A reference to another object of type <see cref="BaseDomainEntity"/> to compare with this object.</param>
/// <returns>
/// <see langword="false"/> if <paramref name="other"/> is equal to <see langword="null"/>, otherwise
/// <see langword="true"/> if <paramref name="other"/> refers to <c>this</c> object, otherwise
/// <see langword="true"/> if <i>the business identities</i> of the current object and the <paramref name="other"/> are equal by value,
/// <see langword="true"/> if <paramref name="other"/> refers to <c>this</c> object, otherwise
/// <see langword="true"/> if <i>the business identities</i> of the current object and the <paramref name="other"/> are equal by value,
/// e.g. <c>BusinessKeyProperty == other.BusinessKeyProperty</c>; otherwise, <see langword="false"/>.
/// </returns>
/// <remarks>
Expand Down
10 changes: 4 additions & 6 deletions Aspects/Model/EFRepository/HiLoIdentity/HiLoStoreIdProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ int IStoreUniqueId<int>.GetNewId<T>(IRepository repository)

var id = DoGetNew<T>(efRepository);

if (id > 0x0FFFFFFFF)
if (id > 0x7FFFFFFF0)
throw new InvalidOperationException(
string.Format(
CultureInfo.InvariantCulture,
"Fatal error: the ID generator for type {0} has reached the maximum value.",
"FATAL ERROR: the ID generator for type {0} has reached the maximum value.",
typeof(T).FullName));

return unchecked((int)id);
Expand Down Expand Up @@ -186,10 +186,8 @@ HiLoIdentityGenerator CreateOrGetFreshGenerator(
if (generator == null)
{
// create a new generator
generator = new HiLoIdentityGenerator(entitySetName, HiLoIdentityGenerator.DefaultMaxLowValue);
localRepository
.Add<HiLoIdentityGenerator>(generator)
;
generator = new HiLoIdentityGenerator(entitySetName);
localRepository.Add(generator);
}

generator.IncrementHighValue();
Expand Down
4 changes: 2 additions & 2 deletions Aspects/Model/EFRepository/SqlStoreIdProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ public IStoreUniqueId<TId> GetProvider<TId>() where TId : IEquatable<TId>
int IStoreUniqueId<int>.GetNewId<T>(IRepository repository)
{
// the value should be ignored by SQL Server
return -1;
return 0;
}
#endregion

#region IStoreUniqueId<long> Members
long IStoreUniqueId<long>.GetNewId<T>(IRepository repository)
{
// the value should be ignored by SQL Server
return -1L;
return 0L;
}
#endregion

Expand Down
23 changes: 19 additions & 4 deletions Aspects/Model/InMemory/MapObjectsRepository.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Threading;
Expand Down Expand Up @@ -60,6 +61,20 @@ public static void Reset()
UnsafeReset();
}

/// <summary>
/// Gets the type of the entity set root.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>System.Type.</returns>
public static Type GetEntitySetRootType(
Type type)
{
var typeList = _entities.FirstOrDefault(kv => kv.Key.IsAssignableFrom(type) ||
type.IsAssignableFrom(kv.Key));

return typeList.Key;
}

/// <summary>
/// Gets the entity list corresponding to the <typeparamref name="T"/>.
/// If the map does not have an entry for the concrete type the method searches for base type entry and
Expand Down Expand Up @@ -160,7 +175,7 @@ public TId GetStoreId<T, TId>()
/// <typeparam name="T">The type of the entity to be added.</typeparam>
/// <param name="entity">The entity to be added.</param>
/// <returns><c>this</c></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId="0#")]
[SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#")]
public IRepository Add<T>(
T entity) where T : BaseDomainEntity
{
Expand Down Expand Up @@ -231,7 +246,7 @@ public T GetByKey<T, TKey>(
/// <typeparam name="T">The type of the entity.</typeparam>
/// <param name="entity">The entity to attach.</param>
/// <returns><c>this</c></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId="0#")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#")]
public IRepository Attach<T>(
T entity) where T : BaseDomainEntity
{
Expand Down Expand Up @@ -272,7 +287,7 @@ public IRepository Attach<T>(
/// If the array is empty, the entire entity will be marked as modified and updated in the store
/// otherwise, only the modified properties will be updated in the store.</param>
/// <returns><c>this</c></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId="0#")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#")]
public IRepository Attach<T>(
T entity,
EntityState state,
Expand Down Expand Up @@ -329,7 +344,7 @@ public IRepository Attach<T>(
/// <typeparam name="T">The type of the entity.</typeparam>
/// <param name="entity">The entity to attach.</param>
/// <returns><c>this</c></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId="0#")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#")]
public IRepository Detach<T>(
T entity) where T : BaseDomainEntity
{
Expand Down
16 changes: 16 additions & 0 deletions Aspects/Model/InMemory/ObjectsRepositorySpecifics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ public Type GetEntityType(
return reference.GetType();
}

/// <summary>
/// Gets the name of the entity set associated with the specified type.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="repository">The repository.</param>
/// <returns>System.String.</returns>
public string GetEntitySetName(
Type type,
IRepository repository)
{
if (repository is ListObjectsRepository)
return null;

return MapObjectsRepository.GetEntitySetRootType(type).FullName;
}

/// <summary>
/// Determines whether the specified reference is a reference to an ORM generated wrapper/proxy of the actual object instead of the actual object itself.
/// Here always returns <see langword="false"/>.
Expand Down
6 changes: 3 additions & 3 deletions Aspects/Model/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
[assembly: AssemblyTitle("vm.Aspect.Model")]
[assembly: AssemblyDescription("Defines the IRepository and related base classes and utilities - a framework of building domain object model.")]

[assembly: AssemblyVersion("1.0.28")]
[assembly: AssemblyFileVersion("1.0.28")]
[assembly: AssemblyInformationalVersion("1.0.28")]
[assembly: AssemblyVersion("1.0.29")]
[assembly: AssemblyFileVersion("1.0.29")]
[assembly: AssemblyInformationalVersion("1.0.29")]

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(
"vm.Aspects.Model.Tests, " +
Expand Down
Loading

0 comments on commit 39efd6c

Please sign in to comment.