Пример #1
0
		public ObjectProjector(SqlQueryProvider queryProvider, DataAccessModel dataAccessModel, SqlDatabaseContext sqlDatabaseContext, SqlQueryFormatResult formatResult)
		{
			this.QueryProvider = queryProvider;
			this.DataAccessModel = dataAccessModel;
			this.SqlDatabaseContext = sqlDatabaseContext;
			this.formatResult = formatResult;
		}
Пример #2
0
        /// <summary>
        /// Gets an <see cref="IAsyncEnumerable{T}"/> for a given SQL query.
        /// </summary>
        /// <typeparam name="TDataAccessModel"></typeparam>
        /// <typeparam name="T">The type of object to return for each value in the result set. Also see <see cref="readObject"/></typeparam>
        /// <typeparam name="TArgs">The anonymous type containing the parameters referenced by <see cref="sql"/></typeparam>
        /// <param name="model">The <see cref="DataAccessModel"/></param>
        /// <param name="readObject">A function that converts an <see cref="IDataReader"/> into an object of type <see cref="T"/></param>
        /// <param name="sql">The SQL query as a string</param>
        /// <param name="args">An anonymous type containing the parameters referenced by <see cref="sql"/></param>
        /// <remarks>
        /// This method does not block. The query is executed on the first call to <see cref="IEnumerator{T}.MoveNext()"/>.
        /// or <see cref="IAsyncEnumerator{T}.MoveNextAsync()"/>.
        /// <para>This method can only be called from within a <see cref="DataAccessScope"/>.</para>
        /// </remarks>
        /// <returns>An <see cref="IAsyncEnumerable{T}"/> that presents an object of type <see cref="T"/> for each row in the result set.</returns>
        public static IAsyncEnumerable <T> ExecuteReader <TDataAccessModel, TArgs, T>(this TDataAccessModel model, Func <IDataReader, T> readObject, string sql, TArgs args)
            where TDataAccessModel : DataAccessModel
        {
            var sqlDatabaseContext = model.GetCurrentSqlDatabaseContext();

            var sqlQueryProvider = new SqlQueryProvider(model, sqlDatabaseContext);

            T ObjectReader(ObjectProjector objectProjector, IDataReader dataReader, int version, object[] dynamicParameters) => readObject(dataReader);

            var prefix = sqlDatabaseContext.SqlDialect.GetSyntaxSymbolString(SqlSyntaxSymbol.ParameterPrefix);
            var key    = new Pair <Type, string>(typeof(TArgs), prefix);

            if (!typeToTypedValuesFunc.TryGetValue(key, out var del))
            {
                del = CreateToTypedValuesFunc <TArgs>(prefix);

                typeToTypedValuesFunc = new Dictionary <Pair <Type, string>, Delegate>(typeToTypedValuesFunc)
                {
                    { key, del }
                };
            }

            var typedValuesFunc = (Func <TArgs, List <TypedValue> >)del;
            var projector       = new ObjectProjector <T>(sqlQueryProvider, model, model.GetCurrentSqlDatabaseContext(), sql, typedValuesFunc(args).ToReadOnlyCollection(), null, ObjectReader);

            return(projector);
        }
        public void OneTimeSetUp()
        {
            var connection = TestDb.InitializeTestDatabase(_variableName, _providerName);

            connection = connection.Replace("\\", "\\\\");
            sut        = SqlQueryProvider.CreateFromJsonDefinition(_rawDefinition.Replace("{SQLCONNECTION}", connection));
        }
        public void GetAllNecessaryNgramsFromTable_InsideList_Empty()
        {
            var wordLists = new List <List <List <string> > >
            {
                new List <List <string> >
                {
                    new List <string> {
                        "a", "b"
                    },
                    new List <string>(),
                    new List <string> {
                        "e", "f", "g"
                    }
                },
                new List <List <string> >
                {
                    new List <string> {
                        "z", "x"
                    },
                    new List <string> {
                        "y"
                    },
                    new List <string> {
                        "w", "v", "u"
                    }
                }
            };

            var provider = new SqlQueryProvider(_names);

            Exception ex = Assert.Throws <ArgumentException>(() => provider.GetAllNecessaryNgramsFromTable(NgramType.Trigram, wordLists));

            Assert.Equal("List<string> inside list has wrong size", ex.Message);
        }
        public void GetTheSameNgramsFromTable_NullListWithNames()
        {
            var provider = new SqlQueryProvider(_names);

            Exception ex = Assert.Throws <ArgumentException>(() => provider.GetTheSameNgramsFromTable(NgramType.Bigram, null));

            Assert.Equal("List<string> 'wordList' has wrong size", ex.Message);
        }
Пример #6
0
 public void Init()
 {
     //var actualColumns = _dataEngine.ColumnMapper.Map<TEntity>(Table);
     //_relatedDbSets = new HashSet<IDbSet>(actualColumns.Where(c => c.ReferenceTable != null).Select(c => _context.GetDbSet(c.ReferenceTable.BaseType)));
     //Columns = _dataEngine.UpdateTable<TEntity>(Table, actualColumns, Columns);
     Provider   = new SqlQueryProvider(_dataEngine, this);
     Expression = Expression.Constant(this);
 }
        public void GetAllNecessaryNgramsFromTable_outsideList_Null()
        {
            var provider = new SqlQueryProvider(_names);

            Exception ex = Assert.Throws <ArgumentException>(() => provider.GetAllNecessaryNgramsFromTable(NgramType.Trigram, null));

            Assert.Equal("List<string> 'wordLists' has wrong size", ex.Message);
        }
        public void CheckWordsInUnigramFromTable_NullList()
        {
            var provider = new SqlQueryProvider(_names);

            Exception ex = Assert.Throws <ArgumentException>(() => provider.CheckWordsInUnigramFromTable(null));

            Assert.Equal("List<string> 'wordList' can't be null", ex.Message);
        }
Пример #9
0
        public override string ToString()
        {
            var optimized = SqlQueryProvider.Optimize(this, typeof(string));

            return(new Sql92QueryFormatter(SqlQueryFormatterOptions.Default)
                   .Format(optimized)
                   .CommandText);
        }
        public void GetTheSameNgramsFromTable_Fourgrams()
        {
            var provider = new SqlQueryProvider(_names);
            var result   = provider.GetTheSameNgramsFromTable(NgramType.Quadrigram, _wordList);

            const string str = @"SELECT * FROM four WHERE Word1='\\a' AND Word2='b' AND Word3='\'c' AND Word4='d'";

            Assert.Equal(str, result);
        }
        public void CreateDbString()
        {
            var provider = new SqlQueryProvider();
            var result   = provider.CreateDbString("name");

            const string str = "CREATE DATABASE IF NOT EXISTS `name` CHARACTER SET utf8 COLLATE utf8_polish_ci;";

            Assert.Equal(str, result);
        }
        public void GetSimilarNgramsFromTable_Trigrams()
        {
            var provider = new SqlQueryProvider(_names);
            var result   = provider.GetSimilarNgramsFromTable(NgramType.Trigram, _wordList);

            const string str = @"SELECT * FROM tri WHERE Word1='\\a' AND Word2='b';";

            Assert.Equal(str, result);
        }
        public void CreateAddProcedureString_Digram()
        {
            var provider = new SqlQueryProvider();
            var result   = provider.CreateAddProcedureString("BaseName", "TableName", 2);

            const string str = "DROP PROCEDURE IF EXISTS BaseName.Add2gram; CREATE PROCEDURE BaseName.Add2gram(in _value int, in _word1 varchar(30), in _word2 varchar(30)) " +
                               "BEGIN SELECT @id:=ID, @val:=Value FROM BaseName.TableName WHERE Word1 = _word1 AND Word2 = _word2; " +
                               "IF @id IS NULL THEN INSERT INTO BaseName.TableName (Value, Word1, Word2) VALUES ( _value, _word1, _word2); " +
                               "ELSE UPDATE BaseName.TableName SET Value = @val + _value WHERE ID = @id; END IF; END";

            Assert.Equal(str, result);
        }
        public void CreateNgramsTableString_Digram()
        {
            var provider = new SqlQueryProvider();
            var result   = provider.CreateNgramsTableString("DbName", "TableName", 2);

            const string str = "CREATE TABLE IF NOT EXISTS `DbName`.`TableName` " +
                               "( `ID` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, " +
                               "`Value` INT NOT NULL, `Word1` VARCHAR(30) NOT NULL, " +
                               "`Word2` VARCHAR(30) NOT NULL ) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_polish_ci;";

            Assert.Equal(str, result);
        }
        public override void Delete(Type type, IEnumerable <DataAccessObject> dataAccessObjects)
        {
            var provider   = new SqlQueryProvider(this.DataAccessModel, this.SqlDatabaseContext);
            var expression = this.BuildDeleteExpression(type, dataAccessObjects);

            if (expression == null)
            {
                return;
            }

            ((ISqlQueryProvider)provider).Execute <int>(expression);
        }
        public void GetTheSameNgramsFromTable_WrongListSize()
        {
            var list = new List <string>
            {
                "a",
            };

            var provider = new SqlQueryProvider(_names);

            Exception ex = Assert.Throws <ArgumentException>(() => provider.GetTheSameNgramsFromTable(NgramType.Bigram, list));

            Assert.Equal("List<string> 'wordList' has wrong size", ex.Message);
        }
        public void InsertOrUpdateNgramString()
        {
            var ngram = new NGram(10, new List <string> {
                "a", "b"
            });

            var provider = new SqlQueryProvider();
            var result   = provider.InsertOrUpdateNgramString(ngram);

            const string str = "CALL Add2gram('10', 'a', 'b');";

            Assert.Equal(str, result);
        }
        public void GetSimilarNgramsFromTable_GoodListSize()
        {
            var list = new List <string>
            {
                "a",
                "b",
                "c"
            };

            var provider = new SqlQueryProvider(_names);
            var ex       = Record.Exception(() => provider.GetSimilarNgramsFromTable(NgramType.Quadrigram, list));

            Assert.IsNotType <ArgumentException>(ex);
        }
Пример #19
0
		private ProjectionBuilder(DataAccessModel dataAccessModel, SqlDatabaseContext sqlDatabaseContext, SqlQueryProvider queryProvider, ProjectionBuilderScope scope)
		{
			this.dataAccessModel = dataAccessModel;
			this.sqlDatabaseContext = sqlDatabaseContext;
			this.queryProvider = queryProvider;
			
			this.scope = scope;

			this.dataReader = Expression.Parameter(typeof(IDataReader), "dataReader");
			this.objectProjector = Expression.Parameter(typeof(ObjectProjector), "objectProjector");
			this.dynamicParameters = Expression.Parameter(typeof (object[]), "dynamicParameters");
			this.versionParameter = Expression.Parameter(typeof(int), "version");
			this.filterParameter = Expression.Parameter(typeof(Func<DataAccessObject, DataAccessObject>), "filter");
		}
        public void GetMultiNgramsFromTable_NullListWithWords()
        {
            var provider = new SqlQueryProvider(_names);
            var wordList = new List <string>
            {
                "a",
                "b",
                "c"
            };

            Exception ex = Assert.Throws <ArgumentException>(() => provider.GetMultiNgramsFromTable(NgramType.Quadrigram, wordList, null));

            Assert.Equal("List<string> 'combinations' has wrong size", ex.Message);
            ex = Assert.Throws <ArgumentException>(() => provider.GetMultiNgramsFromTable(NgramType.Quadrigram, null, wordList));
            Assert.Equal("List<string> 'wordList' has wrong size", ex.Message);
        }
        public void CheckWordsInUnigramFromTable_NormalExample()
        {
            var wordList = new List <string>
            {
                @"\a",
                "b",
                @"'c"
            };

            var provider = new SqlQueryProvider(_names);
            var result   = provider.CheckWordsInUnigramFromTable(wordList);

            const string str = @"SELECT * FROM uni WHERE Word1='\\a' OR Word1='b' OR Word1='\'c';";

            Assert.Equal(str, result);
        }
Пример #22
0
        public static void Example()
        {
            const string prefix    = "A";
            var          provider  = new SqlQueryProvider("Data Source=localhost;User Id=AdoQuery;Password=AdoQuery;");
            var          resultSet = provider.Query <int, string>($@"
                |  select ProductId,
                |         Name
                |    from Product
                |   where Code {prefix:=*}
                |order by ProductId");

            foreach ((int productId, string name) in resultSet)
            {
                Trace.WriteLine($"ProductId = {productId}, Name = {name}");
            }
        }
Пример #23
0
		public static LambdaExpression Build(DataAccessModel dataAccessModel, SqlDatabaseContext sqlDatabaseContext, SqlQueryProvider queryProvider, Expression expression, ProjectionBuilderScope scope, out Expression<Func<IDataReader, object[]>> rootKeys)
		{
			var projectionBuilder = new ProjectionBuilder(dataAccessModel, sqlDatabaseContext, queryProvider, scope);

			var body = projectionBuilder.Visit(expression);

			if (projectionBuilder.scope.rootPrimaryKeys.Count > 0)
			{
				rootKeys = Expression.Lambda<Func<IDataReader, object[]>>(Expression.NewArrayInit(typeof(object), projectionBuilder.scope.rootPrimaryKeys), projectionBuilder.dataReader);
			}
			else
			{
				rootKeys = null;
			}

			return Expression.Lambda(body, projectionBuilder.objectProjector, projectionBuilder.dataReader, projectionBuilder.versionParameter, projectionBuilder.dynamicParameters, projectionBuilder.filterParameter);
		}
Пример #24
0
        public static void Configure(string pathToFolder)
        {
            var folder = pathToFolder ??
                         AppDomain.CurrentDomain.GetData("DataDirectory").ToString();

            var sqlStore = Path.Combine(folder, "sqlstore.json");

            if (File.Exists(sqlStore))
            {
                Logger.Debug("Running on SqlQuery Provider");
                Provider = SqlQueryProvider.CreateFromFileDefinition(sqlStore);
            }
            else
            {
                Logger.Debug("Running on CSV Provider");
                Provider = new CsvMetadataProvider(folder);
            }
        }
Пример #25
0
        public static void DeleteWhere <T>(this DataAccessObjectsQueryable <T> queryable, Expression <Func <T, bool> > condition)
            where T : DataAccessObject
        {
            queryable.DataAccessModel.Flush();

            var transactionContext = queryable.DataAccessModel.AmbientTransactionManager.GetCurrentContext(true);

            using (var acquisition = transactionContext.AcquirePersistenceTransactionContext(queryable.DataAccessModel.GetCurrentSqlDatabaseContext()))
            {
                var expression = (Expression)Expression.Call(null, MethodCache <T> .DeleteMethod, Expression.Constant(queryable, typeof(DataAccessObjectsQueryable <T>)), condition);

                expression = Evaluator.PartialEval(expression);
                expression = QueryBinder.Bind(queryable.DataAccessModel, expression, queryable.ElementType, queryable.ExtraCondition);
                expression = ObjectOperandComparisonExpander.Expand(expression);
                expression = SqlQueryProvider.Optimize(expression, transactionContext.SqlDatabaseContext.SqlDataTypeProvider.GetTypeForEnums());

                acquisition.SqlDatabaseCommandsContext.Delete((SqlDeleteExpression)expression);
            }
        }
        public void InsertNgramsString()
        {
            var ngrams = new List <NGram>
            {
                new NGram(10, new List <string> {
                    "a", "b"
                }),
                new NGram(20, new List <string> {
                    "c", "d"
                })
            };
            var provider = new SqlQueryProvider();
            var result   = provider.InsertNgramsString("TableName", ngrams);

            const string str = "INSERT INTO `TableName` (`Value`, `Word1`, `Word2`) " +
                               "VALUES('10', 'a', 'b'),('20', 'c', 'd');";

            Assert.Equal(str, result);
        }
Пример #27
0
        public DbSet(SqlQueryProvider provider, Expression expression)
        {
            if (provider == null)
            {
                throw new ArgumentNullException("provider");
            }
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            if (!typeof(IQueryable <TEntity>).IsAssignableFrom(expression.Type))
            {
                throw new ArgumentOutOfRangeException("expression");
            }

            Table      = provider.DbSet.Table;
            Context    = provider.DbSet.Context;
            Columns    = provider.DbSet.Columns;
            Provider   = provider;
            Expression = expression;
        }
        public void GetAllNecessaryNgramsFromTable_NormalExample()
        {
            var wordLists = new List <List <List <string> > >
            {
                new List <List <string> >
                {
                    new List <string> {
                        @"\a", "b"
                    },
                    new List <string> {
                        "c", "d"
                    },
                    new List <string> {
                        "e", @"'f", "g"
                    }
                },
                new List <List <string> >
                {
                    new List <string> {
                        "z", "x"
                    },
                    new List <string> {
                        "y"
                    },
                    new List <string> {
                        "w", "v", "u"
                    }
                }
            };

            var provider = new SqlQueryProvider(_names);
            var result   = provider.GetAllNecessaryNgramsFromTable(NgramType.Trigram, wordLists);

            const string str = "SELECT * FROM tri WHERE ( " +
                               @"( Word1='\\a' OR Word1='b' ) AND ( Word2='c' OR Word2='d' ) AND ( Word3='e' OR Word3='\'f' OR Word3='g' ) ) " +
                               "OR ( ( Word1='z' OR Word1='x' ) AND ( Word2='y' ) AND ( Word3='w' OR Word3='v' OR Word3='u' ) );";

            Assert.Equal(str, result);
        }
        public void GetMultiNgramsFromTable_Fourgrams()
        {
            var list = new List <string>
            {
                @"\or1",
                "or2"
            };

            var wordList = new List <string>
            {
                @"\a",
                "b",
                @"'c"
            };

            var provider = new SqlQueryProvider(_names);
            var result   = provider.GetMultiNgramsFromTable(NgramType.Quadrigram, wordList, list);

            const string str = @"SELECT * FROM four WHERE Word1='\\a' AND Word2='b' AND Word3='\'c' AND ( Word4='\\or1' OR Word4='or2' );";

            Assert.Equal(str, result);
        }
        public override void Delete(Type type, IEnumerable <DataAccessObject> dataAccessObjects)
        {
            var typeDescriptor = this.DataAccessModel.GetTypeDescriptor(type);
            var parameter      = Expression.Parameter(typeDescriptor.Type, "value");

            Expression body = null;

            foreach (var dataAccessObject in dataAccessObjects)
            {
                var currentExpression = Expression.Equal(parameter, Expression.Constant(dataAccessObject));

                if (body == null)
                {
                    body = currentExpression;
                }
                else
                {
                    body = Expression.OrElse(body, currentExpression);
                }
            }

            if (body == null)
            {
                return;
            }

            var condition  = Expression.Lambda(body, parameter);
            var expression = (Expression)Expression.Call(Expression.Constant(this.DataAccessModel), MethodInfoFastRef.DataAccessModelGetDataAccessObjectsMethod.MakeGenericMethod(typeDescriptor.Type));

            expression = Expression.Call(MethodInfoFastRef.QueryableWhereMethod.MakeGenericMethod(typeDescriptor.Type), expression, Expression.Quote(condition));
            expression = Expression.Call(MethodInfoFastRef.QueryableExtensionsDeleteMethod.MakeGenericMethod(typeDescriptor.Type), expression);

            var provider = new SqlQueryProvider(this.DataAccessModel, this.SqlDatabaseContext);

            ((ISqlQueryProvider)provider).ExecuteEx <int>(expression);
        }
Пример #31
0
        public override void Delete(Type type, IEnumerable <DataAccessObject> dataAccessObjects)
        {
            var typeDescriptor = this.DataAccessModel.GetTypeDescriptor(type);
            var parameter      = Expression.Parameter(typeDescriptor.Type, "value");

            Expression body = null;

            foreach (var dataAccessObject in dataAccessObjects)
            {
                var currentExpression = Expression.Equal(parameter, Expression.Constant(dataAccessObject));

                if (body == null)
                {
                    body = currentExpression;
                }
                else
                {
                    body = Expression.OrElse(body, currentExpression);
                }
            }

            if (body == null)
            {
                return;
            }

            var condition  = Expression.Lambda(body, parameter);
            var expression = (Expression)Expression.Call(null, GetDeleteMethod(typeDescriptor.Type), Expression.Constant(null, typeDescriptor.Type), condition);

            expression = Evaluator.PartialEval(expression);
            expression = QueryBinder.Bind(this.DataAccessModel, expression, null, null);
            expression = SqlObjectOperandComparisonExpander.Expand(expression);
            expression = SqlQueryProvider.Optimize(expression, this.SqlDatabaseContext.SqlDataTypeProvider.GetTypeForEnums());

            this.Delete((SqlDeleteExpression)expression);
        }
Пример #32
0
        protected IDbCommand BuildInsertCommandForDeflatedPredicated(TypeDescriptor typeDescriptor, DataAccessObject dataAccessObject, List <ObjectPropertyValue> updatedProperties)
        {
            var constantPlaceholdersCount = 0;
            var assignments = new List <Expression>();
            var success     = false;

            var requiresIdentityInsert = dataAccessObject.ToObjectInternal().HasAnyChangedPrimaryKeyServerSideProperties;

            var parameter1 = Expression.Parameter(typeDescriptor.Type);

            foreach (var updated in updatedProperties)
            {
                var placeholder = updated.Value as Expression ?? new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(updated.Value, updated.PropertyType.CanBeNull() ? updated.PropertyType : updated.PropertyType.MakeNullable()));

                if (placeholder.Type != updated.PropertyType)
                {
                    placeholder = Expression.Convert(placeholder, updated.PropertyType);
                }

                var m = TypeUtils.GetMethod(() => default(DataAccessObject).SetColumnValue(default(string), default(int)))
                        .GetGenericMethodDefinition()
                        .MakeGenericMethod(typeDescriptor.Type, updated.PropertyType);

                assignments.Add(Expression.Call(null, m, parameter1, Expression.Constant(updated.PersistedName), placeholder));
            }

            var method = TypeUtils.GetMethod(() => default(IQueryable <DataAccessObject>).InsertHelper(default(Expression <Action <DataAccessObject> >), default(bool)))
                         .GetGenericMethodDefinition()
                         .MakeGenericMethod(typeDescriptor.Type);

            var source     = Expression.Constant(this.DataAccessModel.GetDataAccessObjects(typeDescriptor.Type));
            var selector   = Expression.Lambda(Expression.Block(assignments), parameter1);
            var expression = (Expression)Expression.Call(null, method, source, Expression.Quote(selector), Expression.Constant(requiresIdentityInsert));

            expression = SqlQueryProvider.Bind(this.DataAccessModel, this.sqlDataTypeProvider, expression);
            expression = SqlQueryProvider.Optimize(this.DataAccessModel, this.SqlDatabaseContext, expression);
            var projectionExpression = expression as SqlProjectionExpression;

            expression = projectionExpression.Select.From;

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(expression);

            IDbCommand command = null;

            try
            {
                command             = this.CreateCommand();
                command.CommandText = result.CommandText;

                var cachedValue = new SqlCachedUpdateInsertFormatValue {
                    formatResult = result
                };

                FillParameters(command, cachedValue, null, null);

                success = true;

                return(command);
            }
            finally
            {
                if (!success)
                {
                    command?.Dispose();
                }
            }
        }
Пример #33
0
        protected IDbCommand BuildUpdateCommandForDeflatedPredicated(TypeDescriptor typeDescriptor, DataAccessObject dataAccessObject, bool valuesPredicated, bool primaryKeysPredicated, List <ObjectPropertyValue> updatedProperties, ObjectPropertyValue[] primaryKeys)
        {
            var constantPlaceholdersCount = 0;
            var assignments = new List <Expression>();
            var success     = false;

            var parameter1             = Expression.Parameter(typeDescriptor.Type);
            var requiresIdentityInsert = dataAccessObject.ToObjectInternal().HasAnyChangedPrimaryKeyServerSideProperties;

            foreach (var updated in updatedProperties)
            {
                var value       = updated.Value;
                var placeholder = updated.Value as Expression;

                if (placeholder == null)
                {
                    placeholder = (Expression) new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(updated.Value, updated.PropertyType.CanBeNull() ? updated.PropertyType : updated.PropertyType.MakeNullable()));
                }

                if (placeholder.Type != updated.PropertyType)
                {
                    placeholder = Expression.Convert(placeholder, updated.PropertyType);
                }

                var m = TypeUtils.GetMethod(() => default(DataAccessObject).SetColumnValue(default(string), default(int)))
                        .GetGenericMethodDefinition()
                        .MakeGenericMethod(typeDescriptor.Type, updated.PropertyType);

                assignments.Add(Expression.Call(null, m, parameter1, Expression.Constant(updated.PersistedName), placeholder));
            }

            var parameter = Expression.Parameter(typeDescriptor.Type);

            if (primaryKeys.Length <= 0)
            {
                throw new InvalidOperationException("Expected more than 1 primary key");
            }

            Expression where = null;

            foreach (var primaryKey in primaryKeys)
            {
                var value       = primaryKey.Value;
                var placeholder = primaryKey.Value as Expression;

                if (placeholder == null)
                {
                    placeholder = new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(value, primaryKey.PropertyType.CanBeNull() ? primaryKey.PropertyType : primaryKey.PropertyType.MakeNullable()));
                }

                if (placeholder.Type != primaryKey.PropertyType)
                {
                    placeholder = Expression.Convert(placeholder, primaryKey.PropertyType);
                }

                var pathComponents     = primaryKey.PropertyName.Split('.');
                var propertyExpression = pathComponents.Aggregate <string, Expression>(parameter, Expression.Property);
                var currentExpression  = Expression.Equal(propertyExpression, placeholder);

                where = where == null ? currentExpression : Expression.And(where, currentExpression);
            }

            var predicate = Expression.Lambda(where, parameter);
            var method    = TypeUtils.GetMethod(() => default(IQueryable <DataAccessObject>).UpdateHelper(default(Expression <Action <DataAccessObject> >), requiresIdentityInsert))
                            .GetGenericMethodDefinition()
                            .MakeGenericMethod(typeDescriptor.Type);

            var source     = Expression.Call(null, MethodInfoFastRef.QueryableWhereMethod.MakeGenericMethod(typeDescriptor.Type), Expression.Constant(this.DataAccessModel.GetDataAccessObjects(typeDescriptor.Type)), Expression.Quote(predicate));
            var selector   = Expression.Lambda(Expression.Block(assignments), parameter1);
            var expression = (Expression)Expression.Call(null, method, source, Expression.Quote(selector), Expression.Constant(requiresIdentityInsert));

            expression = SqlQueryProvider.Bind(this.DataAccessModel, this.sqlDataTypeProvider, expression);
            expression = SqlQueryProvider.Optimize(this.DataAccessModel, this.SqlDatabaseContext, expression);
            var projectionExpression = expression as SqlProjectionExpression;

            expression = projectionExpression.Select.From;

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(expression);

            IDbCommand command = null;

            try
            {
                command = this.CreateCommand();

                command.CommandText = result.CommandText;

                var cachedValue = new SqlCachedUpdateInsertFormatValue {
                    formatResult = result
                };

                FillParameters(command, cachedValue, null, null);

                success = true;

                return(command);
            }
            finally
            {
                if (!success)
                {
                    command?.Dispose();
                }
            }
        }
		public override void Delete(Type type, IEnumerable<DataAccessObject> dataAccessObjects)
		{
			var provider = new SqlQueryProvider(this.DataAccessModel, this.SqlDatabaseContext);
			var expression = this.BuildDeleteExpression(type, dataAccessObjects);

			if (expression == null)
			{
				return;
			}

			((ISqlQueryProvider)provider).Execute<int>(expression);
		}