static Query <int> CreateQuery(IDataContext dataContext, EntityDescriptor descriptor, T obj, string tableName, string databaseName, string schemaName, Type type) { var fieldDic = new Dictionary <SqlField, ParameterAccessor>(); var sqlTable = new SqlTable(dataContext.MappingSchema, type); if (tableName != null) { sqlTable.PhysicalName = tableName; } if (databaseName != null) { sqlTable.Database = databaseName; } if (schemaName != null) { sqlTable.Schema = schemaName; } var sqlQuery = new SelectQuery(); ParameterAccessor param = null; var insertOrUpdateStatement = new SqlInsertOrUpdateStatement(sqlQuery); insertOrUpdateStatement.Insert.Into = sqlTable; insertOrUpdateStatement.Update.Table = sqlTable; sqlQuery.From.Table(sqlTable); var ei = new Query <int>(dataContext, null) { Queries = { new QueryInfo { Statement = insertOrUpdateStatement, } } }; var supported = ei.SqlProviderFlags.IsInsertOrUpdateSupported && ei.SqlProviderFlags.CanCombineParameters; // Insert. // foreach (var field in sqlTable.Fields.Select(f => f.Value)) { if (field.IsInsertable && !field.ColumnDescriptor.ShouldSkip(obj, descriptor, SkipModification.Insert)) { if (!supported || !fieldDic.TryGetValue(field, out param)) { param = GetParameter(type, dataContext, field); ei.Queries[0].Parameters.Add(param); if (supported) { fieldDic.Add(field, param); } } insertOrUpdateStatement.Insert.Items.Add(new SqlSetExpression(field, param.SqlParameter)); } else if (field.IsIdentity) { throw new LinqException("InsertOrReplace method does not support identity field '{0}.{1}'.", sqlTable.Name, field.Name); } } // Update. // var keys = sqlTable.GetKeys(true).Cast <SqlField>().ToList(); var fields = sqlTable.Fields.Values.Where(f => f.IsUpdatable && !f.ColumnDescriptor.ShouldSkip(obj, descriptor, SkipModification.Update)) .Except(keys).ToList(); if (keys.Count == 0) { throw new LinqException("InsertOrReplace method requires the '{0}' table to have a primary key.", sqlTable.Name); } var q = ( from k in keys join i in insertOrUpdateStatement.Insert.Items on k equals i.Column select new { k, i } ).ToList(); var missedKey = keys.Except(q.Select(i => i.k)).FirstOrDefault(); if (missedKey != null) { throw new LinqException("InsertOrReplace method requires the '{0}.{1}' field to be included in the insert setter.", sqlTable.Name, missedKey.Name); } if (fields.Count == 0) { throw new LinqException("There are no fields to update in the type '{0}'.", sqlTable.Name); } foreach (var field in fields) { if (!supported || !fieldDic.TryGetValue(field, out param)) { param = GetParameter(type, dataContext, field); ei.Queries[0].Parameters.Add(param); if (supported) { fieldDic.Add(field, param = GetParameter(typeof(T), dataContext, field)); } } insertOrUpdateStatement.Update.Items.Add(new SqlSetExpression(field, param.SqlParameter)); } insertOrUpdateStatement.Update.Keys.AddRange(q.Select(i => i.i)); // Set the query. // if (ei.SqlProviderFlags.IsInsertOrUpdateSupported) { SetNonQueryQuery(ei); } else { MakeAlternativeInsertOrUpdate(ei); } return(ei); }
public void AddParameterAccessor(ParameterAccessor accessor) { ParameterAccessors.Add(accessor); accessor.SqlParameter.AccessorId = ParameterAccessors.Count - 1; }