private static string BuildSqlForDateTimeOffset(DateTimeOffset dateTimeOffset, SqlVersion sqlVersion) { var builder = new StringBuilder(); var sqlGenerator = new SqlGenerator(sqlVersion); var functionExpression = EdmFunctions.CreateDateTimeOffset( DbExpression.FromInt32(dateTimeOffset.Year), DbExpression.FromInt32(dateTimeOffset.Month), DbExpression.FromInt32(dateTimeOffset.Day), DbExpression.FromInt32(dateTimeOffset.Hour), DbExpression.FromInt32(dateTimeOffset.Minute), DbExpression.FromInt32(dateTimeOffset.Second), DbExpression.FromInt32(Convert.ToInt32(dateTimeOffset.Offset.TotalMinutes))); var sqlFragment = SqlFunctionCallHandler.GenerateFunctionCallSql( sqlGenerator, functionExpression); using (var sqlWriter = new SqlWriter(builder)) { sqlFragment.WriteSql(sqlWriter, sqlGenerator); } return(builder.ToString()); }
public override DbExpression Visit(DbScanExpression expression) { //Check if POCO has system Status flag if (expression.Target.ElementType.Members.All(x => x.Name != "SystemStatus")) { return(base.Visit(expression)); } //**** Copied this from the EF team: https://github.com/rowanmiller/Demo-TechEd2014 **** // Just because the entity has the soft delete annotation doesn't mean that // this particular table has the column. This occurs in situation like TPT // inheritance mapping and entity splitting where one type maps to multiple // tables. // We only apply the filter if the column is actually present in this table. // If not, then the query is going to be joining to the table that does have // the column anyway, so the filter will still be applied. var table = (EntityType)expression.Target.ElementType; if (table.Properties.Any(p => p.Name == "Status")) { var binding = expression.Bind(); return (binding.Filter( binding.VariableType.Variable(binding.VariableName) .Property("Status") .NotEqual(DbExpression.FromInt32((int)SystemStatus.Deleted)))); } return(base.Visit(expression)); }
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) { if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace) { var queryCommand = interceptionContext.Result as DbQueryCommandTree; if (queryCommand != null) { var newQuery = queryCommand.Query.Accept(new SoftDeleteQueryVisitor()); interceptionContext.Result = new DbQueryCommandTree( queryCommand.MetadataWorkspace, queryCommand.DataSpace, newQuery); } var deleteCommand = interceptionContext.OriginalResult as DbDeleteCommandTree; if (deleteCommand != null) { //Check if POCO has system Status flag if ( ((EntityType)deleteCommand.Target.VariableType.EdmType).DeclaredMembers.All( x => x.Name != "SystemStatus")) { return; } // Just because the entity has the soft delete annotation doesn't mean that // this particular table has the column. This occurs in situation like TPT // inheritance mapping and entity splitting where one type maps to multiple // tables. // If the table doesn't have the column we just want to leave the row unchanged // since it will be joined to the table that does have the column during query. // We can't no-op, so we just generate an UPDATE command that doesn't set anything. var setClauses = new List <DbModificationClause>(); var table = (EntityType)deleteCommand.Target.VariableType.EdmType; if (table.Properties.Any(p => p.Name == "SystemStatus")) { setClauses.Add(DbExpressionBuilder.SetClause( deleteCommand.Target.VariableType.Variable(deleteCommand.Target.VariableName) .Property("SystemStatus"), DbExpression.FromInt32((int)SystemStatus.Deleted))); } var update = new DbUpdateCommandTree( deleteCommand.MetadataWorkspace, deleteCommand.DataSpace, deleteCommand.Target, deleteCommand.Predicate, setClauses.AsReadOnly(), null); interceptionContext.Result = update; } } }
/// <summary> /// In case of an insert command we always assign the correct value to the tenantId /// </summary> private static bool InterceptInsertCommand(DbCommandTreeInterceptionContext interceptionContext, int userId) { var shoolcontextList = interceptionContext.DbContexts.OfType <SchoolContext>(); if (shoolcontextList.Any(x => x.IsSeeding)) { return(true); } var insertCommand = interceptionContext.Result as DbInsertCommandTree; if (insertCommand != null) { var column = TenantAwareAttribute.GetTenantColumnName(insertCommand.Target.VariableType.EdmType); if (!string.IsNullOrEmpty(column)) { // Create the variable reference in order to create the property var variableReference = DbExpressionBuilder.Variable(insertCommand.Target.VariableType, insertCommand.Target.VariableName); // Create the property to which will assign the correct value var tenantProperty = DbExpressionBuilder.Property(variableReference, column); // Create the set clause, object representation of sql insert command var tenantSetClause = DbExpressionBuilder.SetClause(tenantProperty, DbExpression.FromInt32(userId)); // Remove potential assignment of tenantId for extra safety var filteredSetClauses = insertCommand.SetClauses.Cast <DbSetClause>() .Where(sc => ((DbPropertyExpression)sc.Property).Property.Name != column); // Construct the final clauses, object representation of sql insert command values var finalSetClauses = new ReadOnlyCollection <DbModificationClause>(new List <DbModificationClause>(filteredSetClauses) { tenantSetClause }); // Construct the new command var newInsertCommand = new DbInsertCommandTree( insertCommand.MetadataWorkspace, insertCommand.DataSpace, insertCommand.Target, finalSetClauses, insertCommand.Returning); interceptionContext.Result = newInsertCommand; // True means an interception successfully happened so there is no need to continue return(true); } } return(false); }
public override DbExpression Visit(DbScanExpression expression) { if (this.FilterValue > 0) { // Get the current expression var dbExpression = base.Visit(expression); var binding = expression.Bind(); return(binding.Filter( binding.VariableType .Variable(binding.VariableName) .Property("FilterFieldName") .Equal(DbExpression.FromInt32(this.FilterValue)))); } return(base.Visit(expression)); }
public override DbExpression Visit(DbScanExpression expression) { var column = EdmHelper.GetFactoryColumnName(expression.Target.ElementType); if (!string.IsNullOrEmpty(column)) { // Get the current expression var dbExpression = base.Visit(expression); // Get the current expression binding var currentExpressionBinding = DbExpressionBuilder.Bind(dbExpression); //FactoryId = @Paramname_1 // Create the variable reference in order to create the property var variableReferenceLeftSide = DbExpressionBuilder.Variable(currentExpressionBinding.VariableType, currentExpressionBinding.VariableName); // Create the property based on the variable in order to apply the equality var tenantPropertyLeftSide = DbExpressionBuilder.Property(variableReferenceLeftSide, column); // Create the parameter which is an object representation of a sql parameter. // We have to create a parameter and not perform a direct comparison with Equal function for example // as this logic is cached per query and called only once var tenantParameterLeftSide = DbExpressionBuilder.Parameter(tenantPropertyLeftSide.Property.TypeUsage, FactoryConstants.FactoryIdFilterParameterName); // Apply the equality between property and parameter. var filterExpressionLeftSide = DbExpressionBuilder.Equal(tenantPropertyLeftSide, tenantParameterLeftSide); //1 = @Paramname_2 // Create the variable reference in order to create the property var variableReferenceRightSide = DbExpressionBuilder.Variable(currentExpressionBinding.VariableType, currentExpressionBinding.VariableName); // Create the property based on the variable in order to apply the equality var tenantPropertyRightSide = DbExpression.FromInt32(1); // Create the parameter which is an object representation of a sql parameter. // We have to create a parameter and not perform a direct comparison with Equal function for example // as this logic is cached per query and called only once var tenantParameterRightSide = DbExpressionBuilder.Parameter(TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)), FactoryConstants.FactoryOverrideFilterParameterName); // Apply the equality between property and parameter. var filterExpressionRightSide = DbExpressionBuilder.Equal(tenantPropertyRightSide, tenantParameterRightSide); DbExpressionBuilder. var filterExpression = DbExpressionBuilder.Or(filterExpressionLeftSide, filterExpressionRightSide); // Apply the filtering to the initial query return(DbExpressionBuilder.Filter(currentExpressionBinding, filterExpression)); } return(base.Visit(expression)); }
public override DbExpression Visit(DbScanExpression expression) { var table = (EntityType)expression.Target.ElementType; if (table.Properties.All(p => p.Name != IsDeletedColumnName)) { return(base.Visit(expression)); } var binding = expression.Bind(); return(binding.Filter( binding.VariableType .Variable(binding.VariableName) .Property(IsDeletedColumnName) .NotEqual(DbExpression.FromInt32(1)))); }
private static DbCommandTree HandleDeleteCommand(DbDeleteCommandTree deleteCommand) { var setClauses = new List <DbModificationClause>(); var table = (EntityType)deleteCommand.Target.VariableType.EdmType; if (table.Properties.All(p => p.Name != IsDeletedColumnName)) { return(deleteCommand); } setClauses.Add(DbExpressionBuilder.SetClause( deleteCommand.Target.VariableType.Variable(deleteCommand.Target.VariableName).Property(IsDeletedColumnName), DbExpression.FromInt32(1))); return(new DbUpdateCommandTree( deleteCommand.MetadataWorkspace, deleteCommand.DataSpace, deleteCommand.Target, deleteCommand.Predicate, setClauses.AsReadOnly(), null)); }
/// <summary> /// In case of a delete command we always filter based on the userId /// </summary> static void InterceptDeleteCommand(DbCommandTreeInterceptionContext interceptionContext) { var deleteCommand = interceptionContext.Result as DbDeleteCommandTree; if (deleteCommand != null) { var column = UserAwareAttribute.GetUserColumnName(deleteCommand.Target.VariableType.EdmType); if (!string.IsNullOrEmpty(column)) { // Get the userId (throw an exception if there is none) var userId = GetCurrentUserId(); // Create the variable reference in order to create the property var variableReference = DbExpressionBuilder.Variable(deleteCommand.Target.VariableType, deleteCommand.Target.VariableName); // Create the property to which will assign the correct value var userProperty = DbExpressionBuilder.Property(variableReference, column); var userIdWherePredicate = DbExpressionBuilder.Equal(userProperty, DbExpression.FromInt32(userId)); // The initial predicate is the sql where statement var initialPredicate = deleteCommand.Predicate; // Add to the initial statement the userId statement which translates in sql AND userId = 'value' var finalPredicate = initialPredicate.And(userIdWherePredicate); var newDeleteCommand = new DbDeleteCommandTree( deleteCommand.MetadataWorkspace, deleteCommand.DataSpace, deleteCommand.Target, finalPredicate); interceptionContext.Result = newDeleteCommand; } } }
/// <summary> /// In case of an update command we always filter based on the userId /// </summary> static bool InterceptUpdate(DbCommandTreeInterceptionContext interceptionContext) { var updateCommand = interceptionContext.Result as DbUpdateCommandTree; if (updateCommand != null) { var column = UserAwareAttribute.GetUserColumnName(updateCommand.Target.VariableType.EdmType); if (!string.IsNullOrEmpty(column)) { // Get the userId (throw an exception if there is none) var userId = GetCurrentUserId(); // Create the variable reference in order to create the property var variableReference = DbExpressionBuilder.Variable(updateCommand.Target.VariableType, updateCommand.Target.VariableName); // Create the property to which will assign the correct value var userProperty = DbExpressionBuilder.Property(variableReference, column); // Create the userId where predicate, object representation of sql where userId = value statement var userIdWherePredicate = DbExpressionBuilder.Equal(userProperty, DbExpression.FromInt32(userId)); // Remove potential assignment of userId for extra safety var filteredSetClauses = updateCommand.SetClauses.Cast <DbSetClause>() .Where(sc => ((DbPropertyExpression)sc.Property).Property.Name != column); // Construct the final clauses, object representation of sql insert command values var finalSetClauses = new ReadOnlyCollection <DbModificationClause>(new List <DbModificationClause>(filteredSetClauses)); // The initial predicate is the sql where statement var initialPredicate = updateCommand.Predicate; // Add to the initial statement the userId statement which translates in sql AND UserId = 'value' var finalPredicate = initialPredicate.And(userIdWherePredicate); var newUpdateCommand = new DbUpdateCommandTree( updateCommand.MetadataWorkspace, updateCommand.DataSpace, updateCommand.Target, finalPredicate, finalSetClauses, updateCommand.Returning); interceptionContext.Result = newUpdateCommand; // True means an interception successfully happened so there is no need to continue return(true); } } return(false); }
protected override Expression VisitConstant(ConstantExpression node) { var expression = base.VisitConstant(node); var type = node.Type; if (IsNullableType(type)) { var genericArgs = type.GetGenericArguments(); if ((genericArgs != null) && (genericArgs.Length == 1)) { type = genericArgs[0]; } } if (type == typeof(byte[])) { MapExpressionToDbExpression(expression, DbExpression.FromBinary((byte[])node.Value)); } else if (type == typeof(bool)) { MapExpressionToDbExpression(expression, DbExpression.FromBoolean((bool?)node.Value)); } else if (type == typeof(byte)) { MapExpressionToDbExpression(expression, DbExpression.FromByte((byte?)node.Value)); } else if (type == typeof(DateTime)) { MapExpressionToDbExpression(expression, DbExpression.FromDateTime((DateTime?)node.Value)); } else if (type == typeof(DateTimeOffset)) { MapExpressionToDbExpression(expression, DbExpression.FromDateTimeOffset((DateTimeOffset?)node.Value)); } else if (type == typeof(decimal)) { MapExpressionToDbExpression(expression, DbExpression.FromDecimal((decimal?)node.Value)); } else if (type == typeof(double)) { MapExpressionToDbExpression(expression, DbExpression.FromDouble((double?)node.Value)); } else if (type == typeof(Guid)) { MapExpressionToDbExpression(expression, DbExpression.FromGuid((Guid?)node.Value)); } else if (type == typeof(Int16)) { MapExpressionToDbExpression(expression, DbExpression.FromInt16((Int16?)node.Value)); } else if (type == typeof(Int32)) { MapExpressionToDbExpression(expression, DbExpression.FromInt32((Int32?)node.Value)); } else if (type.IsEnum) { MapExpressionToDbExpression(expression, DbExpression.FromInt32((Int32)node.Value)); } else if (type == typeof(Int64)) { MapExpressionToDbExpression(expression, DbExpression.FromInt64((Int64?)node.Value)); } else if (type == typeof(float)) { MapExpressionToDbExpression(expression, DbExpression.FromSingle((float?)node.Value)); } else if (type == typeof(string)) { MapExpressionToDbExpression(expression, DbExpression.FromString((string)node.Value)); } else { throw new NotImplementedException(string.Format("Unhandled Type of {0} for Constant value {1} in LambdaToDbExpressionVisitor.VisitConstant", node.Type.Name, node.Value ?? "null")); } return(expression); }