private SqlStatement VisitDelete(Expression item, LambdaExpression check) { if (item == null) { throw Error.ArgumentNull("item"); } bool saveAllowDeferred = this.allowDeferred; this.allowDeferred = false; try { MetaTable metaTable = this.services.Model.GetTable(item.Type); Expression source = this.services.Context.GetTable(metaTable.RowType.Type).Expression; Type rowType = metaTable.RowType.Type; // construct identity predicate based on supplied item ParameterExpression p = Expression.Parameter(rowType, "p"); LambdaExpression idPredicate = Expression.Lambda(Expression.Equal(p, item), p); // combine predicate and check expression into single find predicate LambdaExpression findPredicate = idPredicate; if (check != null) { findPredicate = Expression.Lambda(Expression.And(Expression.Invoke(findPredicate, p), Expression.Invoke(check, p)), p); } Expression seq = Expression.Call(typeof(Enumerable), "Where", new Type[] { rowType }, source, findPredicate); SqlSelect ss = new RetypeCheckClause().VisitSelect(this.VisitSequence(seq)); this.allowDeferred = saveAllowDeferred; SqlDelete sd = new SqlDelete(ss, source); return sd; } finally { this.allowDeferred = saveAllowDeferred; } }
private SqlStatement VisitUpdate(Expression item, LambdaExpression check, LambdaExpression resultSelector) { if (item == null) { throw Error.ArgumentNull("item"); } MetaTable metaTable = this.services.Model.GetTable(item.Type); Expression source = this.services.Context.GetTable(metaTable.RowType.Type).Expression; Type rowType = metaTable.RowType.Type; bool saveAllowDeferred = this.allowDeferred; this.allowDeferred = false; try { Expression seq = source; // construct identity predicate based on supplied item ParameterExpression p = Expression.Parameter(rowType, "p"); LambdaExpression idPredicate = Expression.Lambda(Expression.Equal(p, item), p); // combine predicate and check expression into single find predicate LambdaExpression findPredicate = idPredicate; if (check != null) { findPredicate = Expression.Lambda(Expression.And(Expression.Invoke(findPredicate, p), Expression.Invoke(check, p)), p); } seq = Expression.Call(typeof(Enumerable), "Where", new Type[] { rowType }, seq, findPredicate); // source 'query' is based on table + find predicate SqlSelect ss = new RetypeCheckClause().VisitSelect(this.VisitSequence(seq)); // construct update assignments from 'item' info List<SqlAssign> assignments = new List<SqlAssign>(); ConstantExpression conItem = item as ConstantExpression; if (conItem == null) { throw Error.UpdateItemMustBeConstant(); } if (conItem.Value == null) { throw Error.ArgumentNull("item"); } // get changes from data services to construct update command Type entityType = conItem.Value.GetType(); MetaType metaType = this.services.Model.GetMetaType(entityType); ITable table = this.services.Context.GetTable(metaType.InheritanceRoot.Type); foreach (ModifiedMemberInfo mmi in table.GetModifiedMembers(conItem.Value)) { MetaDataMember mdm = metaType.GetDataMember(mmi.Member); assignments.Add( new SqlAssign( sql.Member(ss.Selection, mmi.Member), new SqlValue(mdm.Type, this.typeProvider.From(mdm.Type), mmi.CurrentValue, true, source), source )); } SqlUpdate upd = new SqlUpdate(ss, assignments, source); if (resultSelector == null) { return upd; } SqlSelect select = null; // build select to return result seq = source; seq = Expression.Call(typeof(Enumerable), "Where", new Type[] { rowType }, seq, idPredicate); seq = Expression.Call(typeof(Enumerable), "Select", new Type[] { rowType, resultSelector.Body.Type }, seq, resultSelector); select = this.VisitSequence(seq); select.Where = sql.AndAccumulate( sql.Binary(SqlNodeType.GT, this.GetRowCountExpression(), sql.ValueFromObject(0, false, this.dominatingExpression)), select.Where ); // combine update & select into statement block SqlBlock block = new SqlBlock(source); block.Statements.Add(upd); block.Statements.Add(select); return block; } finally { this.allowDeferred = saveAllowDeferred; } }