Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing collections support #30

Merged
merged 5 commits into from
Sep 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions src/YesSql.Core/Collections/Collection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using System;
using System.Text;

namespace YesSql.Core.Collections
{
public abstract class Collection : IDisposable
{
IDisposable _scope;

public Collection()
{
_scope = CollectionHelper.EnterScope(this);
}

public abstract string GetSafeName();
public static string CreateSafeName(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}

var builder = new StringBuilder();
bool first = true;
foreach (var c in name)
{
if (Char.IsLetter(c) || (!first && Char.IsDigit(c)))
{
builder.Append(c);
}

first = false;
}

return builder.ToString();
}

public void Dispose()
{
_scope.Dispose();
}
}

public static class CollectionExtensions
{
public static string GetPrefixedName(this Collection collection, string table)
{
var name = collection.GetSafeName();

if (String.IsNullOrEmpty(name))
{
return table;
}

return String.Concat(name, "_", table);
}
}

public class DefaultCollection : Collection
{
public DefaultCollection()
{

}

public override string GetSafeName()
{
return "";
}
}

public class TypeCollection<T> : Collection
{
private readonly string _safeName;

public TypeCollection()
{
_safeName = CreateSafeName(typeof(T).Name);

if(String.IsNullOrEmpty(_safeName))
{
throw new ArgumentException("Invalid collection name: " + _safeName);
}
}

public override string GetSafeName()
{
return _safeName;
}
}

public class NamedCollection : Collection
{
private readonly string _safeName;

public NamedCollection(string name)
{
_safeName = CreateSafeName(name);

if (String.IsNullOrEmpty(_safeName))
{
throw new ArgumentException("Invalid collection name: " + _safeName);
}
}

public override string GetSafeName()
{
return _safeName;
}
}
}
90 changes: 90 additions & 0 deletions src/YesSql.Core/Collections/CollectionHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
#if NETSTANDARD1_5
using System.Threading;
#else
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
#endif

namespace YesSql.Core.Collections
{
public class CollectionHelper
{

#if NETSTANDARD1_5
private static readonly AsyncLocal<CollectionStack> _scopes = new AsyncLocal<CollectionStack>();

internal static CollectionStack Scopes
{
get { return _scopes.Value; }
set { _scopes.Value = value; }
}
#else
private static readonly string CollectionDataName = "Collection.Scopes" + AppDomain.CurrentDomain.Id;

internal static CollectionStack Scopes
{
get
{
var handle = CallContext.LogicalGetData(CollectionDataName) as ObjectHandle;

if (handle == null)
{
return null;
}

return handle.Unwrap() as CollectionStack;
}
set
{
CallContext.LogicalSetData(CollectionDataName, new ObjectHandle(value));
}
}
#endif
public static Collection Current
{
get
{
var scopes = GetOrCreateScopes();
return scopes.Peek();
}
}

internal static IDisposable EnterScope(Collection collection)
{
var scopes = GetOrCreateScopes();

var scopeLease = new ScopeLease(scopes);
Scopes = scopes.Push(collection);

return scopeLease;
}

private static CollectionStack GetOrCreateScopes()
{
var scopes = Scopes;
if (scopes == null)
{
scopes = CollectionStack.Empty;
Scopes = scopes;
}

return scopes;
}

private sealed class ScopeLease : IDisposable
{
readonly CollectionStack _collectionStack;

public ScopeLease(CollectionStack collectionStack)
{
_collectionStack = collectionStack;
}

public void Dispose()
{
Scopes = _collectionStack;
}
}
}
}
38 changes: 38 additions & 0 deletions src/YesSql.Core/Collections/CollectionStack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;

namespace YesSql.Core.Collections
{
internal class CollectionStack
{
private readonly CollectionStack _previous;
private readonly Collection _collection;

private CollectionStack()
{

}

private CollectionStack(CollectionStack previous, Collection collection)
{
if (previous == null)
{
throw new ArgumentNullException(nameof(previous));
}

_previous = previous;
_collection = collection;
}

public static readonly CollectionStack Empty = new CollectionStack();

public CollectionStack Push(Collection c)
{
return new CollectionStack(this, c);
}

public Collection Peek()
{
return _collection ?? new DefaultCollection();
}
}
}
5 changes: 4 additions & 1 deletion src/YesSql.Core/Commands/CreateDocumentCommand.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Data.Common;
using System.Threading.Tasks;
using Dapper;
using YesSql.Core.Collections;
using YesSql.Core.Indexes;
using YesSql.Core.Services;
using YesSql.Core.Sql;

namespace YesSql.Core.Commands
Expand All @@ -20,7 +22,8 @@ public CreateDocumentCommand(Document document, string tablePrefix) : base(docum
public override Task ExecuteAsync(DbConnection connection, DbTransaction transaction)
{
var dialect = SqlDialectFactory.For(connection);
var insertCmd = $"insert into [{_tablePrefix}Document] ([Id], [Type]) values (@Id, @Type);";
var documentTable = CollectionHelper.Current.GetPrefixedName(Store.DocumentTable);
var insertCmd = $"insert into [{_tablePrefix}{documentTable}] ([Id], [Type]) values (@Id, @Type);";
return connection.ExecuteScalarAsync<int>(insertCmd, Document, transaction);
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/YesSql.Core/Commands/CreateIndexCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Data.Common;
using YesSql.Core.Collections;
using YesSql.Core.Services;

namespace YesSql.Core.Commands
{
Expand All @@ -26,6 +28,7 @@ public override async Task ExecuteAsync(DbConnection connection, DbTransaction t
{
var dialect = SqlDialectFactory.For(connection);
var type = Index.GetType();
var documentTable = CollectionHelper.Current.GetPrefixedName(Store.DocumentTable);

if (Index is MapIndex)
{
Expand All @@ -40,7 +43,7 @@ public override async Task ExecuteAsync(DbConnection connection, DbTransaction t
var sql = Inserts(type) + $"; {dialect.IdentitySelectString} id";
Index.Id = await connection.ExecuteScalarAsync<int>(sql, Index, transaction);

var bridgeTableName = type.Name + "_Document";
var bridgeTableName = type.Name + "_" + documentTable;
var columnList = $"[{type.Name}Id], [DocumentId]";
var parameterList = $"@Id, @DocumentId";
var bridgeSql = $"insert into [{_tablePrefix}{bridgeTableName}] ({columnList}) values ({parameterList});";
Expand Down
5 changes: 4 additions & 1 deletion src/YesSql.Core/Commands/DeleteDocumentCommand.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Data.Common;
using System.Threading.Tasks;
using Dapper;
using YesSql.Core.Collections;
using YesSql.Core.Indexes;
using YesSql.Core.Services;
using YesSql.Core.Sql;

namespace YesSql.Core.Commands
Expand All @@ -20,7 +22,8 @@ public DeleteDocumentCommand(Document document, string tablePrefix) : base(docum
public override Task ExecuteAsync(DbConnection connection, DbTransaction transaction)
{
var dialect = SqlDialectFactory.For(connection);
var deleteCmd = $"delete from [{_tablePrefix}Document] where [Id] = @Id;";
var documentTable = CollectionHelper.Current.GetPrefixedName(Store.DocumentTable);
var deleteCmd = $"delete from [{_tablePrefix}{documentTable}] where [Id] = @Id;";
return connection.ExecuteAsync(deleteCmd, Document, transaction);
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/YesSql.Core/Commands/DeleteReduceIndexCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Data.Common;
using System.Threading.Tasks;
using YesSql.Core.Indexes;
using YesSql.Core.Collections;
using YesSql.Core.Services;

namespace YesSql.Core.Commands
{
Expand All @@ -17,7 +19,8 @@ public override async Task ExecuteAsync(DbConnection connection, DbTransaction t
{
var name = Index.GetType().Name;

var bridgeTableName = name + "_Document";
var documentTable = CollectionHelper.Current.GetPrefixedName(Store.DocumentTable);
var bridgeTableName = name + "_" + documentTable;
var bridgeSql = $"delete from [{_tablePrefix}{bridgeTableName}] where {name}Id = @Id";

await connection.ExecuteAsync(bridgeSql, new { Id = Index.Id }, transaction);
Expand Down
5 changes: 4 additions & 1 deletion src/YesSql.Core/Commands/UpdateIndexCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Threading.Tasks;
using YesSql.Core.Indexes;
using YesSql.Core.Sql;
using YesSql.Core.Collections;
using YesSql.Core.Services;

namespace YesSql.Core.Commands
{
Expand Down Expand Up @@ -37,7 +39,8 @@ public override async Task ExecuteAsync(DbConnection connection, DbTransaction t
var reduceIndex = Index as ReduceIndex;
if (reduceIndex != null)
{
var bridgeTableName = type.Name + "_Document";
var documentTable = CollectionHelper.Current.GetPrefixedName(Store.DocumentTable);
var bridgeTableName = type.Name + "_" + documentTable;
var columnList = $"[{type.Name}Id], [DocumentId]";
var parameterList = $"@Id, @DocumentId";
var bridgeSqlAdd = $"insert into [{_tablePrefix}{bridgeTableName}] ({columnList}) values ({parameterList});";
Expand Down
3 changes: 3 additions & 0 deletions src/YesSql.Core/Indexes/IIndexProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public interface IIndexProvider
{
void Describe(IDescriptor context);
Type ForType();
string CollectionName { get; set; }
}

public abstract class IndexProvider<T> : IIndexProvider
Expand All @@ -17,6 +18,8 @@ void IIndexProvider.Describe(IDescriptor context)
Describe((DescribeContext<T>)context);
}

public string CollectionName { get; set; }

public Type ForType()
{
return typeof(T);
Expand Down
Loading