Skip to content

Commit

Permalink
Adds identity generation
Browse files Browse the repository at this point in the history
  • Loading branch information
anpete committed Feb 11, 2014
1 parent 34aa877 commit ee9b6f6
Show file tree
Hide file tree
Showing 38 changed files with 558 additions and 135 deletions.
15 changes: 14 additions & 1 deletion Data.sln
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.SqlServer.Un
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{4C4AEEAB-DCD5-4C52-97A2-9187A204AA8F}"
ProjectSection(SolutionItems) = preProject
test\shared\ApiConsistencyFactsBase.cs = test\shared\ApiConsistencyFactsBase.cs
test\shared\ApiConsistencyTestBase.cs = test\shared\ApiConsistencyTestBase.cs
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.SqlServer.FunctionalTest.net45", "test\Microsoft.Data.SqlServer.FunctionalTest\Microsoft.Data.SqlServer.FunctionalTest.net45.csproj", "{B9A39248-3648-4C90-A936-8CD90FFAE7A6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -184,6 +186,16 @@ Global
{3159FABC-0C89-41FF-A279-48665CC068DC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{3159FABC-0C89-41FF-A279-48665CC068DC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{3159FABC-0C89-41FF-A279-48665CC068DC}.Release|x86.ActiveCfg = Release|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Debug|x86.ActiveCfg = Debug|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Release|Any CPU.Build.0 = Release|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{B9A39248-3648-4C90-A936-8CD90FFAE7A6}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -206,5 +218,6 @@ Global
{CA431AD7-2D95-402B-AC17-214994E81943} = {13FEFC36-1C4B-47FC-9086-8D922285D8C4}
{3159FABC-0C89-41FF-A279-48665CC068DC} = {13FEFC36-1C4B-47FC-9086-8D922285D8C4}
{4C4AEEAB-DCD5-4C52-97A2-9187A204AA8F} = {13FEFC36-1C4B-47FC-9086-8D922285D8C4}
{B9A39248-3648-4C90-A936-8CD90FFAE7A6} = {13FEFC36-1C4B-47FC-9086-8D922285D8C4}
EndGlobalSection
EndGlobal
15 changes: 15 additions & 0 deletions src/Microsoft.Data.Entity/Identity/GuidIdentityGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System;
using System.Threading.Tasks;

namespace Microsoft.Data.Entity.Identity
{
public class GuidIdentityGenerator : IIdentityGenerator<Guid>
{
public virtual Task<Guid> NextAsync()
{
return Task.FromResult(Guid.NewGuid());
}
}
}
11 changes: 11 additions & 0 deletions src/Microsoft.Data.Entity/Identity/IIdentityGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System.Threading.Tasks;

namespace Microsoft.Data.Entity.Identity
{
public interface IIdentityGenerator<T>
{
Task<T> NextAsync();
}
}
27 changes: 0 additions & 27 deletions src/Microsoft.Data.Entity/Utilities/StringExtensions.cs

This file was deleted.

18 changes: 18 additions & 0 deletions src/Microsoft.Data.InMemory/InMemoryIdentityGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.Entity.Identity;

namespace Microsoft.Data.InMemory
{
public class InMemoryIdentityGenerator : IIdentityGenerator<long>
{
private static long _current;

public Task<long> NextAsync()
{
return Task.FromResult(Interlocked.Increment(ref _current));
}
}
}
4 changes: 3 additions & 1 deletion src/Microsoft.Data.InMemory/project.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"version" : "0.1-alpha-*",
"dependencies": {},
"dependencies": {
"Microsoft.Data.Entity" : ""
},
"configurations": {
"net45": {},
"k10": {}
Expand Down
113 changes: 113 additions & 0 deletions src/Microsoft.Data.SqlServer/SequenceIdentityGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using JetBrains.Annotations;
#if NET45
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.Entity.Identity;

namespace Microsoft.Data.SqlServer
{
/// <remarks>Not threadsafe</remarks>
public class SequenceIdentityGenerator : IIdentityGenerator<long>
{
public const string DefaultSequenceName = "EF_IdentityGenerator";

private readonly string _connectionString;
private readonly int _increment;
private readonly string _name;
private readonly string _schema;
private readonly string _schemaSql;

private long _current;
private long _max;

public SequenceIdentityGenerator([NotNull] string connectionString)
: this(connectionString, 10)
{
}

public SequenceIdentityGenerator([NotNull] string connectionString, int increment)
: this(connectionString, increment, DefaultSequenceName)
{
}

public SequenceIdentityGenerator([NotNull] string connectionString, int increment, [NotNull] string name)
: this(connectionString, increment, name, null)
{
}

public SequenceIdentityGenerator(
[NotNull] string connectionString, int increment, [NotNull] string name, [CanBeNull] string schema)
{
_connectionString = connectionString;
_increment = increment;
_name = name;
_schema = schema;
_schemaSql = !string.IsNullOrWhiteSpace(_schema) ? "[" + _schema + "]." : string.Empty;
}

public virtual async Task<long> NextAsync()
{
if (_current == _max)
{
using (var connection = new SqlConnection(_connectionString))
{
await connection.OpenAsync();

using (var command = connection.CreateCommand())
{
command.CommandText
= string.Format(
CultureInfo.InvariantCulture,
"SELECT NEXT VALUE FOR {1}[{0}]",
_name,
_schemaSql);

_current = (long)await command.ExecuteScalarAsync();
_max = _current + _increment;
}
}
}

return Interlocked.Increment(ref _current);
}

public virtual async Task EnsureSequenceAsync()
{
using (var connection = new SqlConnection(_connectionString))
{
await connection.OpenAsync();

using (var transaction = connection.BeginTransaction(IsolationLevel.Serializable))
{
using (var command = new SqlCommand())
{
command.Connection = connection;
command.Transaction = transaction;
command.CommandText
= string.Format(
CultureInfo.InvariantCulture,
@"IF NOT EXISTS (SELECT * FROM sys.sequences WHERE name = N'{0}'{1})
CREATE SEQUENCE {2}[{0}] AS bigint START WITH 0 INCREMENT BY {3}",
_name,
!string.IsNullOrWhiteSpace(_schema)
? " AND schema_id = SCHEMA_ID(N'" + _schema + "')"
: string.Empty,
_schemaSql,
_increment);

await command.ExecuteNonQueryAsync();
}

transaction.Commit();
}
}
}
}
}

#endif
36 changes: 36 additions & 0 deletions src/Microsoft.Data.SqlServer/SequentialGuidIdentityGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.Entity.Identity;

namespace Microsoft.Data.SqlServer
{
public class SequentialGuidIdentityGenerator : IIdentityGenerator<Guid>
{
private static long _counter;

static SequentialGuidIdentityGenerator()
{
_counter = DateTime.Now.Ticks;
}

public Task<Guid> NextAsync()
{
var guidBytes = Guid.NewGuid().ToByteArray();
var counterBytes = BitConverter.GetBytes(Interlocked.Increment(ref _counter));

guidBytes[08] = counterBytes[1];
guidBytes[09] = counterBytes[0];
guidBytes[10] = counterBytes[7];
guidBytes[11] = counterBytes[6];
guidBytes[12] = counterBytes[5];
guidBytes[13] = counterBytes[4];
guidBytes[14] = counterBytes[3];
guidBytes[15] = counterBytes[2];

return Task.FromResult(new Guid(guidBytes));
}
}
}
6 changes: 5 additions & 1 deletion src/Microsoft.Data.SqlServer/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
"Microsoft.Data.Relational" : ""
},
"configurations": {
"net45": {},
"net45": {
"dependencies": {
"System.Data" : ""
}
},
"k10": {}
}
}
14 changes: 0 additions & 14 deletions test/Microsoft.Data.Entity.UnitTest/ApiConsistencyFacts.cs

This file was deleted.

34 changes: 34 additions & 0 deletions test/Microsoft.Data.Entity.UnitTest/ApiConsistencyTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System.Linq;
using System.Reflection;
using Microsoft.Data.Entity.Metadata;
using Xunit;

namespace Microsoft.Data.Entity
{
public class ApiConsistencyTest : ApiConsistencyTestBase
{
[Fact]
public void Fluent_api_methods_should_not_return_void()
{
var fluentApiTypes = new[] { typeof(ModelBuilder) };

var voidMethods
= from t in GetAllTypes(fluentApiTypes)
where t.IsVisible
from m in t.GetMethods(PublicInstance)
where m.DeclaringType != null
&& m.DeclaringType.Assembly == TargetAssembly
&& m.ReturnType == typeof(void)
select t.Name + "." + m.Name;

Assert.Equal("", string.Join("\r\n", voidMethods));
}

protected override Assembly TargetAssembly
{
get { return typeof(Metadata.Entity).Assembly; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Microsoft.Data.Entity
{
public class EntityConfigurationFacts
public class EntityConfigurationTest
{
[Fact]
public void Throws_if_no_data_store()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Microsoft.Data.Entity
{
public class EntityServicesFacts
public class EntityServicesTest
{
[Fact]
public void Can_create_default_provider()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Microsoft.Data.Entity.Metadata
{
public class AnnotationFacts
public class AnnotationTest
{
[Fact]
public void Can_create_annotation()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Microsoft.Data.Entity.Metadata
{
public class EntityFacts
public class EntityTest
{
#region Fixture

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Microsoft.Data.Entity.Metadata
{
public class MetadataBaseFacts
public class MetadataBaseTest
{
#region Fixture

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Microsoft.Data.Entity.Metadata
{
public class ModelBuilderFacts
public class ModelBuilderTest
{
#region Fixture

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Microsoft.Data.Entity.Metadata
{
public class ModelFacts
public class ModelTest
{
#region Fixture

Expand Down
Loading

0 comments on commit ee9b6f6

Please sign in to comment.