Skip to content
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
24 changes: 24 additions & 0 deletions Source/EntityFramework.Extended/Batch/IBatchRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data.Entity.Core.Objects;
using System.Linq.Expressions;
using System.Threading.Tasks;
using EntityFramework.Mapping;

namespace EntityFramework.Batch
Expand All @@ -22,6 +23,17 @@ public interface IBatchRunner
int Delete<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query)
where TEntity : class;

/// <summary>
/// Create and runs a batch delete statement asynchronously.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="objectContext">The <see cref="ObjectContext"/> to get connection and metadata information from.</param>
/// <param name="entityMap">The <see cref="EntityMap"/> for <typeparamref name="TEntity"/>.</param>
/// <param name="query">The query to create the where clause from.</param>
/// <returns>The number of rows deleted.</returns>
Task<int> DeleteAsync<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query)
where TEntity : class;

/// <summary>
/// Create and runs a batch update statement.
/// </summary>
Expand All @@ -33,5 +45,17 @@ int Delete<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuer
/// <returns>The number of rows updated.</returns>
int Update<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression)
where TEntity : class;

/// <summary>
/// Create and runs a batch update statement asynchronously.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="objectContext">The <see cref="ObjectContext"/> to get connection and metadata information from.</param>
/// <param name="entityMap">The <see cref="EntityMap"/> for <typeparamref name="TEntity"/>.</param>
/// <param name="query">The query to create the where clause from.</param>
/// <param name="updateExpression">The update expression.</param>
/// <returns>The number of rows updated.</returns>
Task<int> UpdateAsync<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression)
where TEntity : class;
}
}
54 changes: 50 additions & 4 deletions Source/EntityFramework.Extended/Batch/SqlServerBatchRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using EntityFramework.Extensions;
using EntityFramework.Mapping;
using EntityFramework.Reflection;
Expand All @@ -29,7 +30,27 @@ public class SqlServerBatchRunner : IBatchRunner
/// <returns>
/// The number of rows deleted.
/// </returns>
public int Delete<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query)
public int Delete<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query) where TEntity : class
{
return InternalDelete(objectContext, entityMap, query, false).Result;
}

/// <summary>
/// Create and run a batch delete statement asynchronously.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="objectContext">The <see cref="ObjectContext"/> to get connection and metadata information from.</param>
/// <param name="entityMap">The <see cref="EntityMap"/> for <typeparamref name="TEntity"/>.</param>
/// <param name="query">The query to create the where clause from.</param>
/// <returns>
/// The number of rows deleted.
/// </returns>
public Task<int> DeleteAsync<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query) where TEntity : class
{
return InternalDelete(objectContext, entityMap, query, true);
}

private async Task<int> InternalDelete<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query, bool async = false)
where TEntity : class
{
DbConnection deleteConnection = null;
Expand Down Expand Up @@ -89,7 +110,9 @@ public int Delete<TEntity>(ObjectContext objectContext, EntityMap entityMap, Obj

deleteCommand.CommandText = sqlBuilder.ToString();

int result = deleteCommand.ExecuteNonQuery();
int result = async
? await deleteCommand.ExecuteNonQueryAsync()
: deleteCommand.ExecuteNonQuery();

// only commit if created transaction
if (ownTransaction)
Expand Down Expand Up @@ -121,7 +144,28 @@ public int Delete<TEntity>(ObjectContext objectContext, EntityMap entityMap, Obj
/// <returns>
/// The number of rows updated.
/// </returns>
public int Update<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression)
public int Update<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression) where TEntity : class
{
return InternalUpdate(objectContext, entityMap, query, updateExpression, false).Result;
}

/// <summary>
/// Create and run a batch update statement asynchronously.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="objectContext">The <see cref="ObjectContext"/> to get connection and metadata information from.</param>
/// <param name="entityMap">The <see cref="EntityMap"/> for <typeparamref name="TEntity"/>.</param>
/// <param name="query">The query to create the where clause from.</param>
/// <param name="updateExpression">The update expression.</param>
/// <returns>
/// The number of rows updated.
/// </returns>
public Task<int> UpdateAsync<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression) where TEntity : class
{
return InternalUpdate(objectContext, entityMap, query, updateExpression, true);
}

private async Task<int> InternalUpdate<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query, Expression<Func<TEntity, TEntity>> updateExpression, bool async = false)
where TEntity : class
{
DbConnection updateConnection = null;
Expand Down Expand Up @@ -297,7 +341,9 @@ public int Update<TEntity>(ObjectContext objectContext, EntityMap entityMap, Obj

updateCommand.CommandText = sqlBuilder.ToString();

int result = updateCommand.ExecuteNonQuery();
int result = async
? await updateCommand.ExecuteNonQueryAsync()
: updateCommand.ExecuteNonQuery();

// only commit if created transaction
if (ownTransaction)
Expand Down
18 changes: 18 additions & 0 deletions Source/EntityFramework.Extended/Caching/CacheManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EntityFramework.Caching
{
Expand Down Expand Up @@ -285,6 +286,23 @@ public virtual object GetOrAdd(CacheKey cacheKey, Func<CacheKey, object> valueFa
return item;
}

/// <summary>
/// Gets the cache value for the specified key that is already in the dictionary or the new value for the key as returned asynchronously by <paramref name="valueFactory"/>.
/// </summary>
/// <param name="cacheKey">A unique identifier for the cache entry.</param>
/// <param name="valueFactory">The asynchronous function used to generate a value to insert into cache.</param>
/// <param name="cachePolicy">An object that contains eviction details for the cache entry.</param>
/// <returns>
/// The value for the key. This will be either the existing value for the key if the key is already in the dictionary,
/// or the new value for the key as returned by <paramref name="valueFactory"/> if the key was not in the dictionary.
/// </returns>
public virtual Task<object> GetOrAddAsync(CacheKey cacheKey, Func<CacheKey, Task<object>> valueFactory, CachePolicy cachePolicy)
{
var provider = ResolveProvider();
var item = provider.GetOrAddAsync(cacheKey, valueFactory, cachePolicy);

return item;
}

/// <summary>
/// Removes a cache entry from the cache.
Expand Down
13 changes: 13 additions & 0 deletions Source/EntityFramework.Extended/Caching/ICacheProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace EntityFramework.Caching
{
Expand Down Expand Up @@ -39,6 +40,18 @@ public interface ICacheProvider
/// </returns>
object GetOrAdd(CacheKey cacheKey, Func<CacheKey, object> valueFactory, CachePolicy cachePolicy);

/// <summary>
/// Gets the cache value for the specified key that is already in the dictionary or the new value for the key as returned asynchronously by <paramref name="valueFactory"/>.
/// </summary>
/// <param name="cacheKey">A unique identifier for the cache entry.</param>
/// <param name="valueFactory">The asynchronous function used to generate a value to insert into cache.</param>
/// <param name="cachePolicy">A <see cref="CachePolicy"/> that contains eviction details for the cache entry.</param>
/// <returns>
/// The value for the key. This will be either the existing value for the key if the key is already in the cache,
/// or the new value for the key as returned by <paramref name="valueFactory"/> if the key was not in the cache.
/// </returns>
Task<object> GetOrAddAsync(CacheKey cacheKey, Func<CacheKey, Task<object>> valueFactory, CachePolicy cachePolicy);

/// <summary>
/// Removes a cache entry from the cache.
/// </summary>
Expand Down
32 changes: 32 additions & 0 deletions Source/EntityFramework.Extended/Caching/MemoryCacheProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Diagnostics;
using System.Linq;
using System.Runtime.Caching;
using System.Threading.Tasks;

namespace EntityFramework.Caching
{
Expand Down Expand Up @@ -76,6 +77,37 @@ public object GetOrAdd(CacheKey cacheKey, Func<CacheKey, object> valueFactory, C
return value;
}

/// <summary>
/// Gets the cache value for the specified key that is already in the dictionary or the new value for the key as returned asynchronously by <paramref name="valueFactory"/>.
/// </summary>
/// <param name="cacheKey">A unique identifier for the cache entry.</param>
/// <param name="valueFactory">The asynchronous function used to generate a value to insert into cache.</param>
/// <param name="cachePolicy">A <see cref="CachePolicy"/> that contains eviction details for the cache entry.</param>
/// <returns>
/// The value for the key. This will be either the existing value for the key if the key is already in the cache,
/// or the new value for the key as returned by <paramref name="valueFactory"/> if the key was not in the cache.
/// </returns>
public async Task<object> GetOrAddAsync(CacheKey cacheKey, Func<CacheKey, Task<object>> valueFactory, CachePolicy cachePolicy)
{
var key = GetKey(cacheKey);
var cachedResult = MemoryCache.Default.Get(key);

if (cachedResult != null)
{
Debug.WriteLine("Cache Hit : " + key);
return cachedResult;
}

Debug.WriteLine("Cache Miss: " + key);

// get value and add to cache, not bothered
// if it succeeds or not just rerturn the value
var value = await valueFactory(cacheKey);
this.Add(cacheKey, value, cachePolicy);

return value;
}

/// <summary>
/// Removes a cache entry from the cache.
/// </summary>
Expand Down
Loading