Skip to content

Commit 0341656

Browse files
author
zzzprojects
committed
Update to v1.4.4
Update to v1.4.4
1 parent 7a20559 commit 0341656

File tree

524 files changed

+21331
-618
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

524 files changed

+21331
-618
lines changed

src/Z.EntityFramework.Plus.EF5.NET40/BatchDelete/BatchDelete.cs

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,22 @@ public BatchDelete()
134134
/// <returns>The number of rows affected.</returns>
135135
public int Execute<T>(IQueryable<T> query) where T : class
136136
{
137+
// FIX query with visitor
138+
{
139+
var visitor = new BatchDeleteVisitor();
140+
visitor.Visit(query.Expression);
141+
142+
if (visitor.HasOrderBy)
143+
{
144+
query = query.Take(int.MaxValue);
145+
}
146+
147+
if (visitor.HasTake || visitor.HasSkip)
148+
{
149+
BatchSize = 0;
150+
}
151+
}
152+
137153
string expression = query.Expression.ToString();
138154

139155
if (Regex.IsMatch(expression, @"\.Where\(\w+ => False\)"))
@@ -168,34 +184,12 @@ public int Execute<T>(IQueryable<T> query) where T : class
168184
if (command.GetType().Name == "NpgsqlCommand")
169185
{
170186
command.CommandText = command.CommandText.Replace("[", "\"").Replace("]", "\"");
171-
int totalRowAffecteds = 0;
172-
int rowAffecteds = 0;
173-
do
174-
{
175-
if (rowAffecteds > 0 && BatchDelayInterval != 0)
176-
{
177-
Thread.Sleep(BatchDelayInterval);
178-
}
179-
rowAffecteds = (int)command.ExecuteNonQuery();
180-
totalRowAffecteds += rowAffecteds;
181-
} while (rowAffecteds > 0);
182-
187+
int totalRowAffecteds = command.ExecuteNonQuery();
183188
return totalRowAffecteds;
184189
}
185190
else if (command.Connection.GetType().Name.Contains("MySql"))
186191
{
187-
int totalRowAffecteds = 0;
188-
int rowAffecteds = 0;
189-
do
190-
{
191-
if (rowAffecteds > 0 && BatchDelayInterval != 0)
192-
{
193-
Thread.Sleep(BatchDelayInterval);
194-
}
195-
rowAffecteds = (int)command.ExecuteNonQuery();
196-
totalRowAffecteds += rowAffecteds;
197-
} while (rowAffecteds > 0);
198-
192+
int totalRowAffecteds = command.ExecuteNonQuery();
199193
return totalRowAffecteds;
200194
}
201195
else
@@ -248,9 +242,23 @@ public int Execute<T>(IQueryable<T> query) where T : class
248242
dbContext.Database.OpenConnection();
249243
}
250244

251-
if (Executing != null)
245+
if (command.GetType().Name == "NpgsqlCommand")
252246
{
253-
Executing(command);
247+
command.CommandText = command.CommandText.Replace("[", "\"").Replace("]", "\"");
248+
int totalRowAffecteds = command.ExecuteNonQuery();
249+
return totalRowAffecteds;
250+
}
251+
else if (command.Connection.GetType().Name.Contains("MySql"))
252+
{
253+
int totalRowAffecteds = command.ExecuteNonQuery();
254+
return totalRowAffecteds;
255+
}
256+
else
257+
{
258+
if (Executing != null)
259+
{
260+
Executing(command);
261+
}
254262
}
255263

256264
var rowAffecteds = (int)command.ExecuteScalar();
@@ -268,8 +276,11 @@ public int Execute<T>(IQueryable<T> query) where T : class
268276

269277
#if EF5 || EF6
270278
/// <summary>Creates a command to execute the batch operation.</summary>
279+
/// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
280+
/// <typeparam name="T">Generic type parameter.</typeparam>
271281
/// <param name="query">The query.</param>
272282
/// <param name="entity">The schema entity.</param>
283+
/// <param name="visitor">The visitor.</param>
273284
/// <returns>The new command to execute the batch operation.</returns>
274285
internal DbCommand CreateCommand<T>(ObjectQuery query, SchemaEntityType<T> entity)
275286
{
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Linq.Expressions;
2+
3+
namespace Z.EntityFramework.Plus
4+
{
5+
/// <summary>A batch delete visitor.</summary>
6+
public class BatchDeleteVisitor : ExpressionVisitor
7+
{
8+
/// <summary>Gets or sets a value indicating whether the expression contains an OrderBy method.</summary>
9+
/// <value>true if the expression contains an OrderBy metho has order by, false if not.</value>
10+
public bool HasOrderBy { get; set; }
11+
12+
/// <summary>Gets or sets a value indicating whether the expression contains an Skip method.</summary>
13+
/// <value>true if the expression contains an Skip metho has order by, false if not.</value>
14+
public bool HasSkip { get; set; }
15+
16+
/// <summary>Gets or sets a value indicating whether the expression contains an Take method.</summary>
17+
/// <value>true if the expression contains an Take metho has order by, false if not.</value>
18+
public bool HasTake { get; set; }
19+
20+
/// <summary>
21+
/// Visits the children of the <see cref="T:System.Linq.Expressions.MethodCallExpression" />.
22+
/// </summary>
23+
/// <param name="node">The expression to visit.</param>
24+
/// <returns>
25+
/// The modified expression, if it or any subexpression was modified; otherwise, returns the
26+
/// original expression.
27+
/// </returns>
28+
protected override Expression VisitMethodCall(MethodCallExpression node)
29+
{
30+
if (node.Method.Name == "OrderBy")
31+
{
32+
HasOrderBy = true;
33+
}
34+
else if (node.Method.Name == "Skip")
35+
{
36+
HasSkip = true;
37+
}
38+
else if (node.Method.Name == "Take")
39+
{
40+
HasTake = true;
41+
}
42+
43+
return base.VisitMethodCall(node);
44+
}
45+
}
46+
}

src/Z.EntityFramework.Plus.EF5.NET40/BatchUpdate/BatchUpdate.cs

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,17 @@ public BatchUpdate()
127127
/// <returns>The number of rows affected.</returns>
128128
public int Execute<T>(IQueryable<T> query, Expression<Func<T, T>> updateFactory) where T : class
129129
{
130+
// FIX query with visitor
131+
{
132+
var visitor = new BatchUpdateVisitor();
133+
visitor.Visit(query.Expression);
134+
135+
if (visitor.HasOrderBy)
136+
{
137+
query = query.Take(int.MaxValue);
138+
}
139+
}
140+
130141
string expression = query.Expression.ToString();
131142

132143
if (Regex.IsMatch(expression, @"\.Where\(\w+ => False\)"))
@@ -181,8 +192,8 @@ public int Execute<T>(IQueryable<T> query, Expression<Func<T, T>> updateFactory)
181192
}
182193
#elif EFCORE
183194
var dbContext = query.GetDbContext();
184-
var entity = dbContext.Model.FindEntityType(typeof (T));
185-
195+
var entity = dbContext.Model.FindEntityType(typeof(T));
196+
186197
// TODO: Select only key + lambda columns
187198
// var keys = entity.GetKeys().ToList()[0].Properties;
188199
//var queryKeys = query.SelectByName(keys.Select(x => x.Name).ToList());
@@ -285,7 +296,7 @@ internal DbCommand CreateCommand<T>(ObjectQuery query, SchemaEntityType<T> entit
285296

286297
// GET updateSetValues
287298
var setValues = string.Join("," + Environment.NewLine, values.Select((x, i) => x.Item2 is ConstantExpression ?
288-
string.Concat("A.", EscapeName(x.Item1, isMySql), " = ", ((ConstantExpression) x.Item2).Value) :
299+
string.Concat("A.", EscapeName(x.Item1, isMySql), " = ", ((ConstantExpression)x.Item2).Value) :
289300
string.Concat("A.", EscapeName(x.Item1, isMySql), " = @zzz_BatchUpdate_", i)));
290301

291302
// REPLACE template
@@ -367,9 +378,9 @@ public DbCommand CreateCommand(IQueryable query, IEntityType entity, List<Tuple<
367378
if (assembly != null)
368379
{
369380
var type = assembly.GetType("Microsoft.EntityFrameworkCore.SqlServerMetadataExtensions");
370-
var sqlServerEntityTypeMethod = type.GetMethod("SqlServer", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof (IEntityType)}, null);
371-
var sqlServerPropertyMethod = type.GetMethod("SqlServer", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof (IProperty)}, null);
372-
var sqlServer = (IRelationalEntityTypeAnnotations) sqlServerEntityTypeMethod.Invoke(null, new[] {entity});
381+
var sqlServerEntityTypeMethod = type.GetMethod("SqlServer", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IEntityType) }, null);
382+
var sqlServerPropertyMethod = type.GetMethod("SqlServer", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IProperty) }, null);
383+
var sqlServer = (IRelationalEntityTypeAnnotations)sqlServerEntityTypeMethod.Invoke(null, new[] { entity });
373384

374385
// GET mapping
375386
var tableName = string.IsNullOrEmpty(sqlServer.Schema) ?
@@ -380,10 +391,10 @@ public DbCommand CreateCommand(IQueryable query, IEntityType entity, List<Tuple<
380391
var columnKeys = new List<string>();
381392
foreach (var propertyKey in entity.GetKeys().ToList()[0].Properties)
382393
{
383-
var mappingProperty = sqlServerPropertyMethod.Invoke(null, new[] {propertyKey});
394+
var mappingProperty = sqlServerPropertyMethod.Invoke(null, new[] { propertyKey });
384395

385396
var columnNameProperty = mappingProperty.GetType().GetProperty("ColumnName", BindingFlags.Public | BindingFlags.Instance);
386-
columnKeys.Add((string) columnNameProperty.GetValue(mappingProperty));
397+
columnKeys.Add((string)columnNameProperty.GetValue(mappingProperty));
387398
}
388399
#endif
389400
// GET command text template
@@ -410,7 +421,7 @@ public DbCommand CreateCommand(IQueryable query, IEntityType entity, List<Tuple<
410421

411422
// GET updateSetValues
412423
var setValues = string.Join("," + Environment.NewLine, values.Select((x, i) => x.Item2 is ConstantExpression ?
413-
string.Concat("A.[", x.Item1, "] = ", ((ConstantExpression) x.Item2).Value) :
424+
string.Concat("A.[", x.Item1, "] = ", ((ConstantExpression)x.Item2).Value) :
414425
string.Concat("A.[", x.Item1, "] = @zzz_BatchUpdate_", i)));
415426

416427
// REPLACE template
@@ -506,7 +517,7 @@ public List<Tuple<string, object>> GetInnerValues<T>(IQueryable<T> query, Expres
506517
}
507518

508519
var type = assembly.GetType("Microsoft.EntityFrameworkCore.SqlServerMetadataExtensions");
509-
var sqlServerPropertyMethod = type.GetMethod("SqlServer", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof (IProperty)}, null);
520+
var sqlServerPropertyMethod = type.GetMethod("SqlServer", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IProperty) }, null);
510521

511522
#endif
512523
#endif
@@ -529,61 +540,79 @@ public List<Tuple<string, object>> GetInnerValues<T>(IQueryable<T> query, Expres
529540
#elif EFCORE
530541

531542
var property = entity.FindProperty(value.Key);
532-
var mappingProperty = sqlServerPropertyMethod.Invoke(null, new[] {property});
543+
var mappingProperty = sqlServerPropertyMethod.Invoke(null, new[] { property });
533544

534545
var columnNameProperty = mappingProperty.GetType().GetProperty("ColumnName", BindingFlags.Public | BindingFlags.Instance);
535-
var columnName = (string) columnNameProperty.GetValue(mappingProperty);
546+
var columnName = (string)columnNameProperty.GetValue(mappingProperty);
536547
#endif
537548

538549
if (value.Value is Expression)
539550
{
540551
// Oops! the value is not resolved yet!
541552
ParameterExpression parameterExpression = null;
542-
((Expression) value.Value).Visit((ParameterExpression p) =>
553+
((Expression)value.Value).Visit((ParameterExpression p) =>
543554
{
544-
if (p.Type == typeof (T))
555+
if (p.Type == typeof(T))
545556
parameterExpression = p;
546557

547558
return p;
548559
});
549560

550561
// GET the update value by creating a new select command
551-
Type[] typeArguments = {typeof (T), ((Expression) value.Value).Type};
552-
var lambdaExpression = Expression.Lambda(((Expression) value.Value), parameterExpression);
562+
Type[] typeArguments = { typeof(T), ((Expression)value.Value).Type };
563+
var lambdaExpression = Expression.Lambda(((Expression)value.Value), parameterExpression);
553564
var selectExpression = Expression.Call(
554-
typeof (Queryable),
565+
typeof(Queryable),
555566
"Select",
556567
typeArguments,
557568
Expression.Constant(query),
558569
lambdaExpression);
559570
var result = Expression.Lambda(selectExpression).Compile().DynamicInvoke();
560571
#if EF5 || EF6
561572
// GET the select command text
562-
var commandText = ((IQueryable) result).ToString();
573+
var commandText = ((IQueryable)result).ToString();
563574

564575
// GET the 'value' part
565-
var valueSql = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ?
566-
commandText.Substring(6, commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6) :
567-
commandText.Substring(6, commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6);
576+
var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ?
577+
commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 :
578+
commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ?
579+
commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) - 6 :
580+
commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ?
581+
commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 :
582+
commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6;
583+
584+
var valueSql = commandText.Substring(6, pos);
568585

569586
// Add the destination name
570587
valueSql = valueSql.Replace("AS [C1]", "");
571588
valueSql = valueSql.Replace("[Extent1]", "B");
572589
#elif EFCORE
573590
RelationalQueryContext queryContext;
574-
var command = ((IQueryable) result).CreateCommand(out queryContext);
591+
var command = ((IQueryable)result).CreateCommand(out queryContext);
575592
var commandText = command.CommandText;
576593

577594
#if NETSTANDARD1_3
578595
// GET the 'value' part
579-
var valueSql = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ?
580-
commandText.Substring(6, commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) - 6) :
581-
commandText.Substring(6, commandText.IndexOf("FROM", StringComparison.CurrentCultureIgnoreCase) - 6);
596+
var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ?
597+
commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) - 6 :
598+
commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ?
599+
commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.CurrentCultureIgnoreCase) - 6 :
600+
commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ?
601+
commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) - 6 :
602+
commandText.IndexOf("FROM", StringComparison.CurrentCultureIgnoreCase) - 6;
603+
604+
var valueSql = commandText.Substring(6, pos);
582605
#else
583-
// GET the 'value' part
584-
var valueSql = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ?
585-
commandText.Substring(6, commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6) :
586-
commandText.Substring(6, commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6);
606+
// GET the 'value' part
607+
var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ?
608+
commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 :
609+
commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ?
610+
commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) - 6 :
611+
commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ?
612+
commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 :
613+
commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6;
614+
615+
var valueSql = commandText.Substring(6, pos);
587616
#endif
588617

589618
// Add the destination name
@@ -609,7 +638,7 @@ public Dictionary<string, object> ResolveUpdateFromQueryDictValues<T>(Expression
609638
{
610639
var dictValues = new Dictionary<string, object>();
611640
var updateExpressionBody = updateFactory.Body;
612-
var entityType = typeof (T);
641+
var entityType = typeof(T);
613642

614643
// ENSURE: new T() { MemberInitExpression }
615644
var memberInitExpression = updateExpressionBody as MemberInitExpression;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Linq.Expressions;
2+
3+
namespace Z.EntityFramework.Plus
4+
{
5+
/// <summary>A batch update visitor.</summary>
6+
public class BatchUpdateVisitor : ExpressionVisitor
7+
{
8+
/// <summary>Gets or sets a value indicating whether the expression contains an OrderBy method.</summary>
9+
/// <value>true if the expression contains an OrderBy metho has order by, false if not.</value>
10+
public bool HasOrderBy { get; set; }
11+
12+
/// <summary>
13+
/// Visits the children of the <see cref="T:System.Linq.Expressions.MethodCallExpression" />.
14+
/// </summary>
15+
/// <param name="node">The expression to visit.</param>
16+
/// <returns>
17+
/// The modified expression, if it or any subexpression was modified; otherwise, returns the
18+
/// original expression.
19+
/// </returns>
20+
protected override Expression VisitMethodCall(MethodCallExpression node)
21+
{
22+
if (node.Method.Name == "OrderBy")
23+
{
24+
HasOrderBy = true;
25+
}
26+
27+
return base.VisitMethodCall(node);
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)