diff --git a/Source/EntityFramework.Extended/Extensions/FutureExtensions.cs b/Source/EntityFramework.Extended/Extensions/FutureExtensions.cs index 8b18a97..2102df1 100644 --- a/Source/EntityFramework.Extended/Extensions/FutureExtensions.cs +++ b/Source/EntityFramework.Extended/Extensions/FutureExtensions.cs @@ -33,7 +33,7 @@ public static FutureQuery Future(this IQueryable sour throw new ArgumentException("The source query must be of type ObjectQuery or DbQuery.", "source"); var futureContext = GetFutureContext(sourceQuery); - var future = new FutureQuery(sourceQuery, futureContext.ExecuteFutureQueries); + var future = new FutureQuery(sourceQuery, futureContext.ExecuteFutureQueriesAsync); futureContext.AddQuery(future); return future; @@ -69,7 +69,7 @@ public static FutureCount FutureCount(this IQueryable source) throw new ArgumentException("The source query must be of type ObjectQuery or DbQuery.", "source"); var futureContext = GetFutureContext(sourceQuery); - var future = new FutureCount(countQuery, futureContext.ExecuteFutureQueries); + var future = new FutureCount(countQuery, futureContext.ExecuteFutureQueriesAsync); futureContext.AddQuery(future); return future; } @@ -111,7 +111,7 @@ public static FutureValue FutureValue(this IQueryable throw new ArgumentException("The source query must be of type ObjectQuery or DbQuery.", "source"); var futureContext = GetFutureContext(sourceQuery); - var future = new FutureValue(valueQuery, futureContext.ExecuteFutureQueries); + var future = new FutureValue(valueQuery, futureContext.ExecuteFutureQueriesAsync); futureContext.AddQuery(future); return future; } @@ -141,7 +141,7 @@ public static FutureValue FutureFirstOrDefault(this IQueryable throw new ArgumentException("The source query must be of type ObjectQuery or DbQuery.", "source"); var futureContext = GetFutureContext(sourceQuery); - var future = new FutureValue(objectQuery, futureContext.ExecuteFutureQueries); + var future = new FutureValue(objectQuery, futureContext.ExecuteFutureQueriesAsync); futureContext.AddQuery(future); return future; } diff --git a/Source/EntityFramework.Extended/Future/FutureContext.cs b/Source/EntityFramework.Extended/Future/FutureContext.cs index 8a57bea..cd32e35 100644 --- a/Source/EntityFramework.Extended/Future/FutureContext.cs +++ b/Source/EntityFramework.Extended/Future/FutureContext.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Data.Entity.Core.Objects; +using System.Threading.Tasks; namespace EntityFramework.Future { @@ -69,10 +70,12 @@ public bool IsAlive get { return _objectContext.IsAlive; } } + + /// /// Executes the future queries as a single batch. /// - public void ExecuteFutureQueries() + public async Task ExecuteFutureQueriesAsync() { ObjectContext context = ObjectContext; if (context == null) @@ -82,7 +85,7 @@ public void ExecuteFutureQueries() if (runner == null) throw new InvalidOperationException("Could not resolve the IFutureRunner. Make sure IFutureRunner is registered in the Locator.Current container."); - runner.ExecuteFutureQueries(context, FutureQueries); + await runner.ExecuteFutureQueriesAsync(context, FutureQueries); } /// diff --git a/Source/EntityFramework.Extended/Future/FutureCount.cs b/Source/EntityFramework.Extended/Future/FutureCount.cs index 6dad9e4..39c86a5 100644 --- a/Source/EntityFramework.Extended/Future/FutureCount.cs +++ b/Source/EntityFramework.Extended/Future/FutureCount.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Linq; +using System.Threading.Tasks; namespace EntityFramework.Future { @@ -31,7 +32,7 @@ public class FutureCount : FutureValue /// /// The query source to use when materializing. /// The action to execute when the query is accessed. - internal FutureCount(IQueryable query, Action loadAction) + internal FutureCount(IQueryable query, Func loadAction) : base(query, loadAction) { } diff --git a/Source/EntityFramework.Extended/Future/FutureQuery.cs b/Source/EntityFramework.Extended/Future/FutureQuery.cs index bf7b797..a7095e0 100644 --- a/Source/EntityFramework.Extended/Future/FutureQuery.cs +++ b/Source/EntityFramework.Extended/Future/FutureQuery.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading.Tasks; namespace EntityFramework.Future { @@ -30,7 +31,7 @@ public class FutureQuery : FutureQueryBase, IEnumerable /// /// The query source to use when materializing. /// The action to execute when the query is accessed. - internal FutureQuery(IQueryable query, Action loadAction) + internal FutureQuery(IQueryable query, Func loadAction) : base(query, loadAction) { } @@ -43,7 +44,7 @@ internal FutureQuery(IQueryable query, Action loadAction) public IEnumerator GetEnumerator() { // triggers loading future queries - var result = GetResult() ?? Enumerable.Empty(); + var result = GetResultAsync().Result?? Enumerable.Empty(); if (Exception != null) throw new FutureException("An error occurred executing the future query.", Exception); @@ -51,6 +52,15 @@ public IEnumerator GetEnumerator() return result.GetEnumerator(); } + public async Task> ToListAsync() + { + var result = await GetResultAsync(); + + return result.ToList(); + + } + + /// /// Returns an enumerator that iterates through a collection. /// diff --git a/Source/EntityFramework.Extended/Future/FutureQueryBase.cs b/Source/EntityFramework.Extended/Future/FutureQueryBase.cs index fafc15f..7eedc94 100644 --- a/Source/EntityFramework.Extended/Future/FutureQueryBase.cs +++ b/Source/EntityFramework.Extended/Future/FutureQueryBase.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Linq; using EntityFramework.Reflection; +using System.Threading.Tasks; namespace EntityFramework.Future { @@ -15,7 +16,7 @@ namespace EntityFramework.Future [DebuggerDisplay("IsLoaded={IsLoaded}")] public abstract class FutureQueryBase : IFutureQuery { - private readonly Action _loadAction; + private readonly Func _loadAction; private readonly IQueryable _query; private IEnumerable _result; private bool _isLoaded; @@ -25,7 +26,7 @@ public abstract class FutureQueryBase : IFutureQuery /// /// The query source to use when materializing. /// The action to execute when the query is accessed. - protected FutureQueryBase(IQueryable query, Action loadAction) + protected FutureQueryBase(IQueryable query, Func loadAction) { _query = query; _loadAction = loadAction; @@ -36,7 +37,7 @@ protected FutureQueryBase(IQueryable query, Action loadAction) /// Gets the action to execute when the query is accessed. /// /// The load action. - protected Action LoadAction + protected Func LoadAction { get { return _loadAction; } } @@ -71,7 +72,7 @@ IQueryable IFutureQuery.Query /// /// An that can be used to iterate through the collection. /// - protected virtual IEnumerable GetResult() + protected virtual async Task> GetResultAsync() { if (IsLoaded) return _result; @@ -86,7 +87,7 @@ protected virtual IEnumerable GetResult() // invoke the load action on the datacontext // result will be set with a callback to SetResult - LoadAction.Invoke(); + await LoadAction.Invoke(); return _result ?? Enumerable.Empty(); } diff --git a/Source/EntityFramework.Extended/Future/FutureRunner.cs b/Source/EntityFramework.Extended/Future/FutureRunner.cs index f8027de..0b74a51 100644 --- a/Source/EntityFramework.Extended/Future/FutureRunner.cs +++ b/Source/EntityFramework.Extended/Future/FutureRunner.cs @@ -5,6 +5,8 @@ using System.Data.Entity.Core.Objects; using System.Text; using EntityFramework.Reflection; +using System.Threading.Tasks; +using System.Diagnostics; namespace EntityFramework.Future { @@ -13,12 +15,13 @@ namespace EntityFramework.Future /// public class FutureRunner : IFutureRunner { + /// /// Executes the future queries. /// /// The to run the queries against. /// The future queries list. - public void ExecuteFutureQueries(ObjectContext context, IList futureQueries) + public async Task ExecuteFutureQueriesAsync(ObjectContext context, IList futureQueries) { if (context == null) throw new ArgumentNullException("context"); @@ -31,9 +34,20 @@ public void ExecuteFutureQueries(ObjectContext context, IList futu try { +#if DEBUG + System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); + sw.Start(); +#endif using (var command = CreateFutureCommand(context, futureQueries)) - using (var reader = command.ExecuteReader()) + using (var reader = await command.ExecuteReaderAsync()) { +#if DEBUG + Debug.WriteLine("Executing Query: "); + Debug.WriteLine(command.CommandText); + Debug.WriteLine("Time Elapsed: " + sw.ElapsedMilliseconds.ToString("f2") + "ms"); + +#endif + foreach (var futureQuery in futureQueries) { futureQuery.SetResult(context, reader); @@ -110,5 +124,8 @@ private static DbCommand CreateFutureCommand(ObjectContext context, IEnumerable< return command; } + + + } } \ No newline at end of file diff --git a/Source/EntityFramework.Extended/Future/FutureValue.cs b/Source/EntityFramework.Extended/Future/FutureValue.cs index 4e283b2..cb03f0f 100644 --- a/Source/EntityFramework.Extended/Future/FutureValue.cs +++ b/Source/EntityFramework.Extended/Future/FutureValue.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Linq; +using System.Threading.Tasks; namespace EntityFramework.Future { @@ -30,7 +31,7 @@ public class FutureValue : FutureQueryBase /// /// The query source to use when materializing. /// The action to execute when the query is accessed. - internal FutureValue(IQueryable query, Action loadAction) + internal FutureValue(IQueryable query, Func loadAction) : base(query, loadAction) { } @@ -60,7 +61,7 @@ public T Value { _hasValue = true; - var result = GetResult() ?? Enumerable.Empty(); + var result = GetResultAsync().Result ?? Enumerable.Empty(); UnderlyingValue = result.FirstOrDefault(); } @@ -76,6 +77,12 @@ public T Value } } + public async Task ValueAsync() + { + return (await GetResultAsync()).FirstOrDefault(); + } + + /// /// Performs an implicit conversion from to T. /// diff --git a/Source/EntityFramework.Extended/Future/IFutureContext.cs b/Source/EntityFramework.Extended/Future/IFutureContext.cs index 165f50a..d912335 100644 --- a/Source/EntityFramework.Extended/Future/IFutureContext.cs +++ b/Source/EntityFramework.Extended/Future/IFutureContext.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; namespace EntityFramework.Future { @@ -14,10 +15,12 @@ public interface IFutureContext /// The future queries. IList FutureQueries { get; } + + /// /// Executes the future queries. /// - void ExecuteFutureQueries(); + Task ExecuteFutureQueriesAsync(); /// /// Adds the future query to the waiting queries list on this context. diff --git a/Source/EntityFramework.Extended/Future/IFutureRunner.cs b/Source/EntityFramework.Extended/Future/IFutureRunner.cs index dc303f0..979c7f3 100644 --- a/Source/EntityFramework.Extended/Future/IFutureRunner.cs +++ b/Source/EntityFramework.Extended/Future/IFutureRunner.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Data.Entity.Core.Objects; +using System.Threading.Tasks; namespace EntityFramework.Future { @@ -9,11 +10,13 @@ namespace EntityFramework.Future /// public interface IFutureRunner { + + /// /// Executes the future queries. /// /// The to run the queries against. /// The future queries list. - void ExecuteFutureQueries(ObjectContext context, IList futureQueries); + Task ExecuteFutureQueriesAsync(ObjectContext context, IList futureQueries); } } \ No newline at end of file