/// <summary> /// Insert all entities selected by the specified query, using an anonymous initializer for specifying setters. <typeparamref name="TTarget"/> /// must be explicitly provided, e.g. <c>source.InsertInto<Cat, Dog>(c => new {...})</c>. The insert operation is performed in the /// database without reading the entities out of it. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <typeparam name="TTarget">The type of the entities to insert. Must be explicitly provided.</typeparam> /// <param name="source">The query matching entities source of the data to insert.</param> /// <param name="expression">The expression projecting a source entity to an anonymous object representing /// the entity to insert.</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns>The number of inserted entities.</returns> public static Task <int> InsertIntoAsync <TSource, TTarget>(this IQueryable <TSource> source, Expression <Func <TSource, object> > expression, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <int>(cancellationToken)); } try { return(ExecuteInsertAsync <TSource, TTarget>(source, DmlExpressionRewriter.PrepareExpressionFromAnonymous(source.Expression, expression), cancellationToken)); } catch (Exception ex) { return(Task.FromException <int>(ex)); } }
/// <summary> /// Perform an <c>update versioned</c> on all entities selected by the specified query. The update operation is performed in the database without /// reading the entities out of it. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <param name="source">The query matching the entities to update.</param> /// <param name="expression">The update setters expressed as a member initialization of updated entities, e.g. /// <c>x => new Dog { Name = x.Name, Age = x.Age + 5 }</c>. Unset members are ignored and left untouched.</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns>The number of updated entities.</returns> public static Task <int> UpdateVersionedAsync <TSource>(this IQueryable <TSource> source, Expression <Func <TSource, TSource> > expression, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <int>(cancellationToken)); } try { return(ExecuteUpdateAsync(source, DmlExpressionRewriter.PrepareExpression(source.Expression, expression), true, cancellationToken)); } catch (Exception ex) { return(Task.FromException <int>(ex)); } }
/// <summary> /// Update all entities selected by the specified query, using an anonymous initializer for specifying setters. The update operation is performed /// in the database without reading the entities out of it. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <param name="source">The query matching the entities to update.</param> /// <param name="expression">The assignments expressed as an anonymous object, e.g. /// <c>x => new { Name = x.Name, Age = x.Age + 5 }</c>. Unset members are ignored and left untouched.</param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns>The number of updated entities.</returns> public static Task <int> UpdateAsync <TSource>(this IQueryable <TSource> source, Expression <Func <TSource, object> > expression, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <int>(cancellationToken)); } try { return(ExecuteUpdateAsync(source, DmlExpressionRewriter.PrepareExpressionFromAnonymous(source.Expression, expression), false, cancellationToken)); } catch (Exception ex) { return(Task.FromException <int>(ex)); } }
/// <summary> /// Insert the entities. The insert operation is performed in the database without reading the entities out of it. Will use /// <c>INSERT INTO [...] SELECT FROM [...]</c> in the database. /// </summary> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns>The number of inserted entities.</returns> public Task <int> InsertAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <int>(cancellationToken)); } try { return(_source.ExecuteInsertAsync <TSource, TTarget>(DmlExpressionRewriter.PrepareExpression <TSource>(_source.Expression, _assignments.List), cancellationToken)); } catch (Exception ex) { return(Task.FromException <int>(ex)); } }
/// <summary> /// Perform an <c>update versioned</c> on the entities. The update operation is performed in the database without reading the entities out of it. /// </summary> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns>The number of updated entities.</returns> public Task <int> UpdateVersionedAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <int>(cancellationToken)); } try { return(_source.ExecuteUpdateAsync(DmlExpressionRewriter.PrepareExpression <TSource>(_source.Expression, _assignments.List), true, cancellationToken)); } catch (Exception ex) { return(Task.FromException <int>(ex)); } }
public static Expression PrepareExpressionFromAnonymous <TSource>(Expression sourceExpression, Expression <Func <TSource, object> > expression) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } // Anonymous initializations are not implemented as member initialization but as plain constructor call. var newExpression = expression.Body as NewExpression ?? throw new ArgumentException("The expression must be an anonymous initialization, e.g. x => new { Name = x.Name, Age = x.Age + 5 }"); var instance = new DmlExpressionRewriter(expression.Parameters); instance.AddSettersFromAnonymousConstructor(newExpression, ""); return(PrepareExpression <TSource>(sourceExpression, instance._assignments)); }
public static Expression PrepareExpression <TSource, TTarget>(Expression sourceExpression, Expression <Func <TSource, TTarget> > expression) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } var memberInitExpression = expression.Body as MemberInitExpression ?? throw new ArgumentException("The expression must be a member initialization, e.g. x => new Dog { Name = x.Name, Age = x.Age + 5 }, " + // If someone call InsertSyntax<TSource>.As(source => new {...}), the code will fail here, so we have to hint at how to correctly // use anonymous initialization too. "or an anonymous initialization with an explicitly specified target type when inserting"); if (memberInitExpression.Type != typeof(TTarget)) { throw new TypeMismatchException($"Expecting an expression of exact type {typeof(TTarget).AssemblyQualifiedName} " + $"but got {memberInitExpression.Type.AssemblyQualifiedName}"); } var instance = new DmlExpressionRewriter(expression.Parameters); instance.AddSettersFromBindings(memberInitExpression.Bindings, ""); return(PrepareExpression <TSource>(sourceExpression, instance._assignments)); }
/// <summary> /// Perform an <c>update versioned</c> on the entities. The update operation is performed in the database without reading the entities out of it. /// </summary> /// <returns>The number of updated entities.</returns> public int UpdateVersioned() { return(_source.ExecuteUpdate(DmlExpressionRewriter.PrepareExpression <TSource>(_source.Expression, _assignments.List), true)); }
/// <summary> /// Perform an <c>update versioned</c> on all entities selected by the specified query, using an anonymous initializer for specifying setters. /// The update operation is performed in the database without reading the entities out of it. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <param name="source">The query matching the entities to update.</param> /// <param name="expression">The assignments expressed as an anonymous object, e.g. /// <c>x => new { Name = x.Name, Age = x.Age + 5 }</c>. Unset members are ignored and left untouched.</param> /// <returns>The number of updated entities.</returns> public static int UpdateVersioned <TSource>(this IQueryable <TSource> source, Expression <Func <TSource, object> > expression) { return(ExecuteUpdate(source, DmlExpressionRewriter.PrepareExpressionFromAnonymous(source.Expression, expression), true)); }
/// <summary> /// Update all entities selected by the specified query. The update operation is performed in the database without reading the entities out of it. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <param name="source">The query matching the entities to update.</param> /// <param name="expression">The update setters expressed as a member initialization of updated entities, e.g. /// <c>x => new Dog { Name = x.Name, Age = x.Age + 5 }</c>. Unset members are ignored and left untouched.</param> /// <returns>The number of updated entities.</returns> public static int Update <TSource>(this IQueryable <TSource> source, Expression <Func <TSource, TSource> > expression) { return(ExecuteUpdate(source, DmlExpressionRewriter.PrepareExpression(source.Expression, expression), false)); }
/// <summary> /// Insert all entities selected by the specified query, using an anonymous initializer for specifying setters. <typeparamref name="TTarget"/> /// must be explicitly provided, e.g. <c>source.InsertInto<Cat, Dog>(c => new {...})</c>. The insert operation is performed in the /// database without reading the entities out of it. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <typeparam name="TTarget">The type of the entities to insert. Must be explicitly provided.</typeparam> /// <param name="source">The query matching entities source of the data to insert.</param> /// <param name="expression">The expression projecting a source entity to an anonymous object representing /// the entity to insert.</param> /// <returns>The number of inserted entities.</returns> public static int InsertInto <TSource, TTarget>(this IQueryable <TSource> source, Expression <Func <TSource, object> > expression) { return(ExecuteInsert <TSource, TTarget>(source, DmlExpressionRewriter.PrepareExpressionFromAnonymous(source.Expression, expression))); }