Пример #1
0
        private DatasetVersion applyTupleChanges(DatasetVersion workingCopyVersion
            , ref List<DataTupleVersion> tupleVersionsTobeAdded, ref List<DataTuple> tuplesTobeDeleted, ref List<DataTuple> tuplesTobeEdited
            , ICollection<DataTuple> createdTuples, ICollection<DataTuple> editedTuples, ICollection<long> deletedTuples, ICollection<DataTuple> unchangedTuples = null)
        {
            // do nothing with unchanged for now
            #region Process Newly Created Tuples

            /// associate newly created tuples to the new version
            /// try using bulk copy or stateless sessions for large amount of new tuples. it should also apply on deleted tuples.
            /// Take care of automatic flushing and try to prevent or reduce it while the edit process is not finished.
            if (createdTuples != null && createdTuples.Count() > 0)
            {
                // is not working cause of the item.Dematerialize();
                //Parallel.ForEach(createdTuples, item =>
                //{
                //    item.Dematerialize();
                //    // commented for the performance testing purpose. see the efects and uncomment if needed-> workingCopyVersion.PriliminaryTuples.Add(item);
                //    item.DatasetVersion = workingCopyVersion;
                //    item.TupleAction = TupleAction.Created;
                //    item.Timestamp = workingCopyVersion.Timestamp;

                //});
                foreach (var item in createdTuples)
                {
                    //item.Dematerialize();
                    // commented for the performance testing purpose. see the efects and uncomment if needed-> workingCopyVersion.PriliminaryTuples.Add(item);
                    item.DatasetVersion = workingCopyVersion;
                    item.TupleAction = TupleAction.Created;
                    item.Timestamp = workingCopyVersion.Timestamp;
                }
            }

            #endregion

            if ((editedTuples != null && editedTuples.Count() > 0) || (deletedTuples != null && deletedTuples.Count() > 0))
            {

                // latest version is the latest checked in version. it is the previous version in comparison to the working copy version.
                // the checks to see whether the dataset is checked out are considered to be done before
                DatasetVersion latestCheckedInVersion = workingCopyVersion.Dataset.Versions.OrderByDescending(p => p.Timestamp).FirstOrDefault(p => p.Status == DatasetVersionStatus.CheckedIn);
                if (latestCheckedInVersion == null) // there is no previous version, means its the first version. In this case there is no need to handle deleted and editedVersion items!
                    return (workingCopyVersion);

                // the edit and delete candiates know the exact ID of the target tuple, so no need to load the whole tuples in advance. in worst case the number of single tuple match queries will increase
                //List<DataTuple> latestVersionEffectiveTuples = getPrimaryTuples(workingCopyVersion); //latestVersionEffectiveTuples =  DataTupleRepo.Get(p=>p.DatasetVersion ==  null).ToList();

                #region Process Edited Tuples

                /// manage editedVersion tuples:
                /// 1: create a DataTupleVersion based on its previous version
                /// 2: Remove the original from the original version
                /// 3: add them to the version
                /// 4: set timestamp for the editedVersion ones
                if (editedTuples != null && editedTuples.Count() > 0)
                {
                    // this part of the code loads the original tuples that are claimed edited. The edited collection is indeed one package of changes submitted in this round
                    // so its used to load only the relevant portion of the tuples. this avoid loading all the tuples asscoiated with the current version. also avoid N times querying the DB, each time to retreive one tuple
                    // Seems a moderate solution between the two extreme.
                    List<Int64> editedTupleIds = editedTuples.Select(t => t.Id).ToList(); // All the IDs of edited tuples of the current package
                    List<DataTuple> oraginalsOfEditedTuples = DataTupleRepo.Get(p => editedTupleIds.Contains(p.Id)).ToList(); // all the original tuples edited in the current package

                    //Parallel.ForEach(editedTuples, edited => // not able to use parallel for now, because the tuplesTobeEdited gets shared between threads for writting in it, which causes synch problems
                    foreach (var edited in editedTuples)
                    {
                        DataTuple orginalTuple = oraginalsOfEditedTuples.SingleOrDefault(p => p.Id == edited.Id); //DataTupleRepo.Get(edited.Id);// latestVersionEffectiveTuples.Where(p => p.Id == editedVersion.Id).Single();//maybe preliminary tuples are enough
                        if (orginalTuple == null || orginalTuple.Id <= 0) // maybe the tuple is in the edited list by a mistake!
                            continue;
                        //check if the history record for this data tuple has been created before. in cases of multiple edits in a single version for example
                        if (DataTupleVerionRepo.Query(p => p.OriginalTuple.Id == orginalTuple.Id && p.DatasetVersion.Id == orginalTuple.DatasetVersion.Id).Count() <= 0) // it is the first time the orginalTuple is getting editedVersion. so add a history record. the history record, keeps the tuple as was before the first edit!
                        {
                            DataTupleVersion tupleVersion = new DataTupleVersion()
                            {
                                TupleAction = TupleAction.Edited,
                                Extra = orginalTuple.Extra,
                                //Id = orginalTuple.Id,
                                OrderNo = orginalTuple.OrderNo,
                                Timestamp = orginalTuple.Timestamp,
                                XmlAmendments = orginalTuple.XmlAmendments,
                                XmlVariableValues = orginalTuple.XmlVariableValues,
                                OriginalTuple = orginalTuple,
                                DatasetVersion = orginalTuple.DatasetVersion, //latestCheckedInVersion,
                                ActingDatasetVersion = workingCopyVersion,
                            };
                            //DataTuple merged =
                            //orginalTuple.History.Add(tupleVersion);
                        }

                        //need a better way to preserve changes during the fetch of the original tuple. Maybe deep copy/ evict/ merge works
                        //XmlDocument xmlVariableValues = new XmlDocument();
                        //xmlVariableValues.LoadXml(editedVersion.XmlVariableValues.AsString());

                        // dematerialize just for the purpose of synching the xml fields with the object properties.
                        edited.Dematerialize();

                        orginalTuple.TupleAction = TupleAction.Edited;
                        orginalTuple.OrderNo = edited.OrderNo;
                        orginalTuple.XmlAmendments = null;
                        orginalTuple.XmlAmendments = edited.XmlAmendments;
                        orginalTuple.XmlVariableValues = null;
                        orginalTuple.XmlVariableValues = edited.XmlVariableValues;

                        //System.Diagnostics.Debug.Print(editedVersion.XmlVariableValues.AsString());
                        //editedVersion.VariableValues.ToList().ForEach(p => System.Diagnostics.Debug.Print(p.Value.ToString()));
                        //System.Diagnostics.Debug.Print(xmlVariableValues.AsString());

                        orginalTuple.DatasetVersion = workingCopyVersion;
                        orginalTuple.Timestamp = workingCopyVersion.Timestamp;
                        tuplesTobeEdited.Add(orginalTuple);
                        //workingCopyVersion.PriliminaryTuples.Add(detached);

                        //latestCheckedInVersion.PriliminaryTuples.Remove(orginalTuple);
                        //latestVersionEffectiveTuples.Remove(orginalTuple);
                    }
                    //); //parallel for each
                }

                #endregion

                #region Process Deleted Tuples

                /// manage deleted tuples:
                /// 1: create a DataTupleVersion based on their previous version
                /// 2: Remove them from the latest version
                /// 3: DO NOT add them to the new version
                /// 4: DO NOT set timestamp for the deleted ones

                if (deletedTuples != null && deletedTuples.Count() > 0)
                {
                    //Parallel.ForEach(deletedTuples, deleted =>  // the tuplesTobeDeleted gets shared between the threads!

                    // use the tuple iterator to reduce the # of DB fetchs
                    DataTupleIterator tupleIterator = new DataTupleIterator(deletedTuples.ToList(), this);
                    // load the ID all the tuple versions that are already linked to the tobe deleted tuples.
                    //This reduces the number of selects on the tuple versions, because most of the tuples have no version
                    List<long> tupleVersionIds = DataTupleVerionRepo.Query(p => deletedTuples.Contains(p.OriginalTuple.Id)).Select(p=>p.Id).ToList();
                    foreach (var deleted in tupleIterator)
                    {
                        DataTuple originalTuple = (DataTuple)deleted; // DataTupleRepo.Get(deleted.Id);// latestVersionEffectiveTuples.Where(p => p.Id == deleted.Id).Single();
                        // check if the tuple has a previous history record. for example may be it was first editedVersion and now is going to be deleted. in two different edits but in one version

                        DataTupleVersion tupleVersion;
                        // check if the tuple has a history record
                        if (tupleVersionIds.Contains(originalTuple.Id))
                        {
                            tupleVersion = DataTupleVerionRepo.Get(originalTuple.Id);
                            // there is a previous history record, with tuple action equal to Edit or even Delete!
                            tupleVersion.TupleAction = TupleAction.Deleted;
                        }
                        else // there is no previous record, so create one
                        {
                            tupleVersion = new DataTupleVersion()
                            {
                                TupleAction = TupleAction.Deleted,
                                Extra = originalTuple.Extra,
                                //Id = orginalTuple.Id,
                                OrderNo = originalTuple.OrderNo,
                                Timestamp = originalTuple.Timestamp,
                                XmlAmendments = originalTuple.XmlAmendments,
                                XmlVariableValues = originalTuple.XmlVariableValues,
                                //OriginalTuple = orginalTuple,
                                DatasetVersion = originalTuple.DatasetVersion, // latestCheckedInVersion,
                                ActingDatasetVersion = workingCopyVersion,
                            };
                        }

                        tupleVersion.OriginalTuple = null;

                        // /////////////////////////////////////////
                        // try avoid accessing to the PriliminaryTuples, they cause loading all the tuples!!
                        // ////////////////////////////////////////

                        // -> latestCheckedInVersion.PriliminaryTuples.Remove(originalTuple);
                        // check whether the deleted tuples are removed from the datatuples table!!!!!
                        //latestVersionEffectiveTuples.Remove(originalTuple);
                        // -> workingCopyVersion.PriliminaryTuples.Remove(originalTuple);
                        //try
                        //{
                        //    //originalTuple.History.ToList().ForEach(p => p.OriginalTuple = null);
                        //}
                        //catch { }

                        //originalTuple.History.Clear();
                        originalTuple.DatasetVersion = null;

                        tuplesTobeDeleted.Add(originalTuple);
                        tupleVersionsTobeAdded.Add(tupleVersion);
                    }
                    //); // parralel for each loop
                }

                #endregion
            }
            return (workingCopyVersion);
        }