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);
            }
Example #2
0
 public void AddParameterAccessor(ParameterAccessor accessor)
 {
     ParameterAccessors.Add(accessor);
     accessor.SqlParameter.AccessorId = ParameterAccessors.Count - 1;
 }