// Constructors

        public PersistRequestBuilderContext(PersistRequestBuilderTask task, ModelMapping mapping, NodeConfiguration nodeConfiguration)
        {
            Task              = task;
            Type              = task.Type;
            Mapping           = mapping;
            NodeConfiguration = nodeConfiguration;

            var affectedIndexes = Type.AffectedIndexes.Where(index => index.IsPrimary).ToList();

            affectedIndexes.Sort((left, right) => {
                if (left.ReflectedType.GetAncestors().Contains(right.ReflectedType))
                {
                    return(1);
                }
                if (right.ReflectedType.GetAncestors().Contains(left.ReflectedType))
                {
                    return(-1);
                }
                return(0);
            });
            AffectedIndexes = new ReadOnlyList <IndexInfo>(affectedIndexes);

            PrimaryIndex      = Task.Type.Indexes.PrimaryIndex;
            ParameterBindings = new Dictionary <ColumnInfo, PersistParameterBinding>();

            if (task.ValidateVersion)
            {
                VersionParameterBindings = new Dictionary <ColumnInfo, PersistParameterBinding>();
            }
        }
        private SqlPersistTask CreateInsertTask(PersistAction action)
        {
            var entityState = action.EntityState;
            var tuple       = entityState.Tuple.ToRegular();
            var request     = GetOrBuildRequest(action.Node, PersistRequestBuilderTask.Insert(entityState.Type));

            return(new SqlPersistTask(entityState.Key, request, tuple));
        }
        private ICollection <PersistRequest> GetOrBuildRequest(StorageNode node, PersistRequestBuilderTask task)
        {
            var cache = node.PersistRequestCache;
            ICollection <PersistRequest> result;

            if (cache.TryGetValue(task, out result))
            {
                return(result);
            }
            result = requestBuilder.Build(node, task);
            return(cache.TryAdd(task, result) ? result : cache[task]);
        }
        internal ICollection <PersistRequest> Build(StorageNode node, PersistRequestBuilderTask task)
        {
            var context = new PersistRequestBuilderContext(task, node.Mapping, node.Configuration);
            List <PersistRequest> result;

            switch (task.Kind)
            {
            case PersistRequestKind.Insert:
                result = BuildInsertRequest(context);
                break;

            case PersistRequestKind.Remove:
                result = BuildRemoveRequest(context);
                break;

            case PersistRequestKind.Update:
                result = BuildUpdateRequest(context);
                break;

            default:
                throw new ArgumentOutOfRangeException("task.Kind");
            }

            // Merging requests for servers which support batching
            // unless version validation is requested.
            if (providerInfo.Supports(ProviderFeatures.Batches) && result.Count > 1 && !task.ValidateVersion)
            {
                var batch    = SqlDml.Batch();
                var bindings = new HashSet <PersistParameterBinding>();
                foreach (var request in result)
                {
                    batch.Add(request.Statement);
                    bindings.UnionWith(request.ParameterBindings);
                }
                var batchRequest = CreatePersistRequest(batch, bindings, node.Configuration);
                batchRequest.Prepare();
                return(new List <PersistRequest> {
                    batchRequest
                }.AsReadOnly());
            }

            foreach (var item in result)
            {
                item.Prepare();
            }

            return(result.AsReadOnly());
        }
        private SqlPersistTask CreateRemoveTask(PersistAction action, bool validateVersion)
        {
            var entityState = action.EntityState;
            var tuple       = entityState.Key.Value;

            if (validateVersion)
            {
                var versionTuple    = entityState.DifferentialTuple.Origin.ToRegular();
                var availableFields = versionTuple.GetFieldStateMap(TupleFieldState.Available);
                var request         = GetOrBuildRequest(action.Node,
                                                        PersistRequestBuilderTask.RemoveWithVersionCheck(entityState.Type, availableFields));
                return(new SqlPersistTask(entityState.Key, request, tuple, versionTuple, true));
            }
            else
            {
                var request = GetOrBuildRequest(action.Node, PersistRequestBuilderTask.Remove(entityState.Type));
                return(new SqlPersistTask(entityState.Key, request, tuple));
            }
        }