Skip to content

Commit 43ddc8b

Browse files
author
zzzprojects
committed
Add Async + Fix Reader Issue + Fix Cast + Fix GetModel + Fix Execute for BatchDelete
Add Async + Fix Reader Issue + Fix Cast + Fix GetModel + Fix Execute for BatchDelete
1 parent 09ee75e commit 43ddc8b

File tree

13 files changed

+289
-26
lines changed

13 files changed

+289
-26
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Description: Entity Framework Bulk Operations & Utilities (EF Bulk SaveChanges, Insert, Update, Delete, Merge | LINQ Query Cache, Deferred, Filter, IncludeFilter, IncludeOptimize | Audit)
2+
// Website & Documentation: https://github.com/zzzprojects/Entity-Framework-Plus
3+
// Forum & Issues: https://github.com/zzzprojects/EntityFramework-Plus/issues
4+
// License: https://github.com/zzzprojects/EntityFramework-Plus/blob/master/LICENSE
5+
// More projects: http://www.zzzprojects.com/
6+
// Copyright © ZZZ Projects Inc. 2014 - 2016. All rights reserved.
7+
8+
#if EF5 || EF6
9+
using System.Data.Entity;
10+
11+
#elif EFCORE
12+
using Microsoft.Data.Entity;
13+
14+
#endif
15+
16+
namespace Z.EntityFramework.Plus
17+
{
18+
public static partial class AuditExtensions
19+
{
20+
/// <summary>Audits and saves all changes made in this context to the underlying database.</summary>
21+
/// <param name="context">The context used to audits and saves all changes made.</param>
22+
/// <param name="audit">The audit to use to add changes made to the context.</param>
23+
/// <returns>The number of objects written to the underlying database.</returns>-
24+
public static int SaveChanges(this DbContext context, Audit audit)
25+
{
26+
audit.PreSaveChanges(context);
27+
var rowAffecteds = context.SaveChanges();
28+
audit.PostSaveChanges();
29+
30+
if (audit.CurrentOrDefaultConfiguration.AutoSavePreAction != null)
31+
{
32+
audit.CurrentOrDefaultConfiguration.AutoSavePreAction(context, audit);
33+
context.SaveChanges();
34+
}
35+
36+
return rowAffecteds;
37+
}
38+
}
39+
}

src/shared/Z.EF.Plus.BatchDelete.Shared/BatchDelete.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ public int Execute<T>(IQueryable<T> query) where T : class
201201
innerObjectQuery.Context.Connection.Open();
202202
}
203203

204+
if (Executing != null)
205+
{
206+
Executing(command);
207+
}
208+
204209
if (command.GetType().Name == "NpgsqlCommand")
205210
{
206211
command.CommandText = command.CommandText.Replace("[", "\"").Replace("]", "\"");
@@ -224,11 +229,6 @@ public int Execute<T>(IQueryable<T> query) where T : class
224229
}
225230
else
226231
{
227-
if (Executing != null)
228-
{
229-
Executing(command);
230-
}
231-
232232
var rowAffecteds = (int)command.ExecuteScalar();
233233
return rowAffecteds;
234234
}
@@ -272,6 +272,11 @@ public int Execute<T>(IQueryable<T> query) where T : class
272272
dbContext.Database.OpenConnection();
273273
}
274274

275+
if (Executing != null)
276+
{
277+
Executing(command);
278+
}
279+
275280
if (command.GetType().Name == "NpgsqlCommand")
276281
{
277282
command.CommandText = command.CommandText.Replace("[", "\"").Replace("]", "\"");
@@ -283,13 +288,6 @@ public int Execute<T>(IQueryable<T> query) where T : class
283288
int totalRowAffecteds = command.ExecuteNonQuery();
284289
return totalRowAffecteds;
285290
}
286-
else
287-
{
288-
if (Executing != null)
289-
{
290-
Executing(command);
291-
}
292-
}
293291

294292
var rowAffecteds = (int)command.ExecuteScalar();
295293
return rowAffecteds;

src/shared/Z.EF.Plus.BatchUpdate.Shared/BatchUpdate.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ public List<Tuple<string, object>> GetInnerValues<T>(IQueryable<T> query, Expres
847847

848848
// Add the destination name
849849
valueSql = valueSql.Replace("AS [C1]", "");
850+
valueSql = valueSql.Replace("AS `C1`", "");
850851

851852
var listReplace = new List<string>()
852853
{
@@ -865,6 +866,21 @@ public List<Tuple<string, object>> GetInnerValues<T>(IQueryable<T> query, Expres
865866
"[Filter4]",
866867
"[Filter5]",
867868
"[Filter6]",
869+
"`Extent1`",
870+
"`Extent2`",
871+
"`Extent3`",
872+
"`Extent4`",
873+
"`Extent5`",
874+
"`Extent6`",
875+
"`Extent7`",
876+
"`Extent8`",
877+
"`Extent9`",
878+
"`Filter1`",
879+
"`Filter2`",
880+
"`Filter3`",
881+
"`Filter4`",
882+
"`Filter5`",
883+
"`Filter6`",
868884
};
869885

870886
// Replace the first value found only!
@@ -883,6 +899,11 @@ public List<Tuple<string, object>> GetInnerValues<T>(IQueryable<T> query, Expres
883899
valueSql = valueSql.Substring(0, valueSql.LastIndexOf('[') - 4);
884900
}
885901

902+
if (valueSql.LastIndexOf('`') != -1 && valueSql.Substring(0, valueSql.LastIndexOf('`')).EndsWith(" AS ", StringComparison.InvariantCulture))
903+
{
904+
valueSql = valueSql.Substring(0, valueSql.LastIndexOf('`') - 4);
905+
}
906+
886907
#elif EFCORE
887908
RelationalQueryContext queryContext;
888909
var command = ((IQueryable)result).CreateCommand(out queryContext);

src/shared/Z.EF.Plus.QueryFuture.Shared/BaseQueryFuture.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,14 @@ public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQuer
160160
logger = loggerField.GetValue(queryCompilationContextFactory);
161161
}
162162

163+
163164
// CREATE connection
164165
{
165166
QueryConnection = context.Database.GetService<IRelationalConnection>();
167+
166168
var innerConnection = new CreateEntityConnection(QueryConnection.DbConnection, null);
167169
var innerConnectionField = typeof(RelationalConnection).GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance);
170+
168171
innerConnectionField.SetValue(QueryConnection, new Microsoft.EntityFrameworkCore.Internal.LazyRef<DbConnection>(() => innerConnection));
169172
}
170173

src/shared/Z.EF.Plus.QueryFuture.Shared/QueryFutureBatch.cs

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
using System.Linq.Expressions;
1313
using System.Reflection;
1414
using System.Text;
15-
15+
using System.Threading.Tasks;
1616
#if EF5
1717
using System.Data.EntityClient;
1818
using System.Data.Objects;
@@ -25,6 +25,7 @@
2525
#elif EFCORE
2626
using Microsoft.EntityFrameworkCore;
2727
using Microsoft.EntityFrameworkCore.Query;
28+
using Microsoft.EntityFrameworkCore.Storage;
2829

2930
#endif
3031

@@ -163,12 +164,113 @@ public void ExecuteQueries()
163164
}
164165
}
165166

167+
#if NET45
168+
/// <summary>Executes deferred query lists.</summary>
169+
public async Task ExecuteQueriesAsync()
170+
{
171+
if (Queries.Count == 0)
172+
{
173+
// Already all executed
174+
return;
175+
}
176+
177+
#if EFCORE
178+
if (IsInMemory)
179+
{
180+
foreach (var query in Queries)
181+
{
182+
query.ExecuteInMemory();
183+
}
184+
Queries.Clear();
185+
return;
186+
}
187+
#endif
188+
189+
if (Queries.Count == 1)
190+
{
191+
Queries[0].GetResultDirectly();
192+
Queries.Clear();
193+
return;
194+
}
195+
196+
#if EF5 || EF6
197+
var connection = (EntityConnection)Context.Connection;
198+
#elif EFCORE
199+
if (IsInMemory)
200+
{
201+
foreach (var query in Queries)
202+
{
203+
query.ExecuteInMemory();
204+
}
205+
return;
206+
}
207+
208+
var connection = Context.Database.GetDbConnection();
209+
#endif
210+
var command = CreateCommandCombined();
211+
212+
var ownConnection = false;
213+
214+
try
215+
{
216+
if (connection.State != ConnectionState.Open)
217+
{
218+
await connection.OpenAsync().ConfigureAwait(false);
219+
ownConnection = true;
220+
}
221+
222+
using (command)
223+
{
224+
#if EF5
225+
using (var reader = command.ExecuteReader())
226+
{
227+
foreach (var query in Queries)
228+
{
229+
query.SetResult(reader);
230+
await reader.NextResultAsync().ConfigureAwait(false);
231+
}
232+
}
233+
#elif EF6
234+
var interceptionContext = Context.GetInterceptionContext();
235+
using (var reader = DbInterception.Dispatch.Command.Reader(command, new DbCommandInterceptionContext(interceptionContext)))
236+
{
237+
foreach (var query in Queries)
238+
{
239+
query.SetResult(reader);
240+
await reader.NextResultAsync().ConfigureAwait(false);
241+
}
242+
}
243+
#elif EFCORE
244+
using (var reader = command.ExecuteReader())
245+
{
246+
var createEntityDataReader = new CreateEntityDataReader(reader);
247+
foreach (var query in Queries)
248+
{
249+
query.SetResult(createEntityDataReader);
250+
await reader.NextResultAsync().ConfigureAwait(false);
251+
}
252+
}
253+
#endif
254+
}
255+
256+
Queries.Clear();
257+
}
258+
finally
259+
{
260+
if (ownConnection)
261+
{
262+
connection.Close();
263+
}
264+
}
265+
}
266+
#endif
267+
166268
/// <summary>Creates a new command combining deferred queries.</summary>
167269
/// <returns>The combined command created from deferred queries.</returns>
168270
protected DbCommand CreateCommandCombined()
169271
{
170272
var command = Context.CreateStoreCommand();
171-
273+
172274
var sb = new StringBuilder();
173275
var queryCount = 1;
174276

@@ -232,7 +334,7 @@ protected DbCommand CreateCommandCombined()
232334
}
233335
}
234336
#elif EFCORE
235-
337+
236338
RelationalQueryContext queryContext;
237339
var queryCommand = query.CreateExecutorAndGetCommand(out queryContext);
238340
var sql = queryCommand.CommandText;

src/shared/Z.EF.Plus.QueryFuture.Shared/QueryFutureEnumerable.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Collections.Generic;
1010
using System.Data.Common;
1111
using System.Linq;
12+
using System.Threading.Tasks;
1213
#if EF5
1314
using System.Data.Objects;
1415

@@ -74,6 +75,53 @@ IEnumerator IEnumerable.GetEnumerator()
7475
return GetEnumerator();
7576
}
7677

78+
#if NET45
79+
public async Task<List<T>> ToListAsync()
80+
{
81+
if (!HasValue)
82+
{
83+
await OwnerBatch.ExecuteQueriesAsync().ConfigureAwait(false);
84+
}
85+
86+
if (_result == null)
87+
{
88+
return new List<T>();
89+
}
90+
91+
using (var enumerator = _result.GetEnumerator())
92+
{
93+
var list = new List<T>();
94+
while (enumerator.MoveNext())
95+
{
96+
list.Add(enumerator.Current);
97+
}
98+
return list;
99+
}
100+
}
101+
102+
public async Task<T[]> ToArrayAsync()
103+
{
104+
if (!HasValue)
105+
{
106+
await OwnerBatch.ExecuteQueriesAsync().ConfigureAwait(false);
107+
}
108+
109+
if (_result == null)
110+
{
111+
return new T[0];
112+
}
113+
114+
using (var enumerator = _result.GetEnumerator())
115+
{
116+
var list = new List<T>();
117+
while (enumerator.MoveNext())
118+
{
119+
list.Add(enumerator.Current);
120+
}
121+
return list.ToArray();
122+
}
123+
}
124+
#endif
77125

78126
/// <summary>Sets the result of the query deferred.</summary>
79127
/// <param name="reader">The reader returned from the query execution.</param>

src/shared/Z.EF.Plus.QueryFuture.Shared/QueryFutureValue.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Data;
1111
using System.Data.Common;
1212
using System.Linq;
13+
using System.Threading.Tasks;
1314
#if EF5
1415
using System.Data.Objects;
1516

@@ -65,6 +66,20 @@ public TResult Value
6566
}
6667
}
6768

69+
#if NET45
70+
/// <summary>Gets the value of the future query.</summary>
71+
/// <value>The value of the future query.</value>
72+
public async Task<TResult> ValueAsync()
73+
{
74+
if (!HasValue)
75+
{
76+
await OwnerBatch.ExecuteQueriesAsync().ConfigureAwait(false);
77+
}
78+
79+
return _result;
80+
}
81+
#endif
82+
6883
/// <summary>Sets the result of the query deferred.</summary>
6984
/// <param name="reader">The reader returned from the query execution.</param>
7085
public override void SetResult(DbDataReader reader)

src/shared/Z.EF.Plus.QueryIncludeFilter.Shared/QueryIncludeFilterParentQueryable`.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@ public IQueryable CreateQueryable()
179179

180180
if (newQuery == null)
181181
{
182-
newQuery = OriginalQueryable.Select(x => new {x, q = childQuery});
182+
// REFLECTION: newQuery.CreateAnonymousFromQuery<TElement>(newQuery, childQuery);
183+
var createAnonymousFromQueryMethodGeneric = createAnonymousFromQueryMethod.MakeGenericMethod(OriginalQueryable.ElementType, childQuery.ElementType);
184+
newQuery = (IQueryable)createAnonymousFromQueryMethodGeneric.Invoke(this, new object[] { OriginalQueryable, childQuery });
183185
}
184186
else
185187
{

src/shared/Z.EF.Plus._Core.Shared/EFCore/CreateEntity/CreateEntityCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ protected override DbParameter CreateDbParameter()
9898

9999
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
100100
{
101-
return OriginalDataReader;
101+
return OriginalDataReader == null || OriginalDataReader.IsClosed ? OriginalCommand.ExecuteReader(behavior) : OriginalDataReader;
102102
}
103103
}
104104
}

0 commit comments

Comments
 (0)