Exemple #1
0
 public void Reset()
 {
     if (m_version != m_collection.m_version)
     {
         throw new InvalidOperationException("Collection was modified; enumeration operation may not execute");
     }
     m_currentElement = null;
 }
Exemple #2
0
        public override void Merge(XStorageObjectBase p_xobj)
        {
            base.Merge(p_xobj);
            XStorageObjectToSave xobj = p_xobj as XStorageObjectToSave;

            if (xobj == null)
            {
                Debug.Fail("Некорректная реализация XStorageObjectBase::Merge");
                throw new ArgumentException();
            }
            UpdateTS = UpdateTS | xobj.UpdateTS;
            if (xobj.IsToInsert)
            {
                m_state = XStorageObjectState.ToInsert;
            }
            foreach (string sPropName in xobj.Props.Keys)
            {
                if (!Props.Contains(sPropName))
                {
                    // свойства не было - добавим
                    Props[sPropName] = xobj.Props[sPropName];
                }
                else
                {
                    XStorageObjectPropMergeModes mergeModeThis    = GetPropMergeMode(sPropName);
                    XStorageObjectPropMergeModes mergeModeForeign = xobj.GetPropMergeMode(sPropName);
                    // если хотя бы для одного свойства стоит флаг "слабой" проверки, то отключаем проверку на совпадание значений свойств
                    if (mergeModeThis == XStorageObjectPropMergeModes.Replace)
                    {
                        Debug.Assert(mergeModeForeign != XStorageObjectPropMergeModes.Replace, "Два свойства с признаком перезаписи - это некорректная ситуация");
                        // у текущего св-ва задан атрибут перезаписи, поэтому оставляем его в неприкосновенности (даже проверки не делаем)
                    }
                    else if (mergeModeForeign == XStorageObjectPropMergeModes.Replace)
                    {
                        Props[sPropName] = xobj.Props[sPropName];
                    }
                    else
                    {
                        if (!isPropsEquals(Props[sPropName], xobj.Props[sPropName]))
                        {
                            throw new XMergeConflictException("Значения свойста " + sPropName + " отличаются: '" + Props[sPropName] + "' и '" + xobj.Props[sPropName] + "'");
                        }
                    }
                }
            }

            // смерджим словарь свойств, данные которых загружены механизмом кусочного сохранения
            if (xobj.PropertiesWithChunkedData.Count > 0)
            {
                foreach (string sPropName in xobj.PropertiesWithChunkedData.Keys)
                {
                    PropertiesWithChunkedData[sPropName] = xobj.PropertiesWithChunkedData[sPropName];
                }
            }

            ParticipateInUniqueIndex = xobj.ParticipateInUniqueIndex | ParticipateInUniqueIndex;
        }
Exemple #3
0
        public override void Merge(XStorageObjectBase p_xobj)
        {
            base.Merge(p_xobj);
            XStorageObjectToDelete xobj = p_xobj as XStorageObjectToDelete;

            if (xobj == null)
            {
                Debug.Fail("Некорректная реализация XStorageObjectBase::Merge");
                throw new ArgumentException();
            }
        }
Exemple #4
0
        public void Add(XStorageObjectBase xobj)
        {
            IDictionary objects = (IDictionary)m_types[xobj.ObjectType];

            if (objects == null)
            {
                objects = new Hashtable(1);
                m_types.Add(xobj.ObjectType, objects);
            }
            objects.Add(xobj.ObjectID, xobj);
            ++m_version;
        }
Exemple #5
0
        public XDatagram GetDatagram(DomainObjectDataSet dataSet)
        {
            XDatagram   dg         = new XDatagram();
            IEnumerator enumerator = dataSet.GetModifiedObjectsEnumerator(false);

            while (enumerator.MoveNext())
            {
                XStorageObjectBase xobj = createXStorageObject((DomainObjectData)enumerator.Current);
                add(xobj);
                createObjectsFromLinks(xobj);
            }
            fillDatagram(dg);
            return(dg);
        }
Exemple #6
0
        /// <summary>
        /// Добавляет ко множеству xml-объект
        /// </summary>
        /// <param name="xmlObject"></param>
        private void Add(XmlElement xmlObject, XTypeInfo typeInfo)
        {
            XStorageObjectBase xobj       = CreateXStorageObject(xmlObject, typeInfo);
            XStorageObjectBase xobjExists = (XStorageObjectBase)m_objectsDictionary[xobj.ObjectID];

            if (xobjExists != null)
            {
                merge(xobjExists, xobj);
            }
            else
            {
                m_objects.Add(xobj);
                m_objectsDictionary.Add(xobj.ObjectID, xobj);
            }
        }
Exemple #7
0
        /// <summary>
        /// Добавление объекта в датаграмму. Если объект с таким типом и идентификатором уже существует
        /// </summary>
        /// <param name="xobj"></param>
        protected XStorageObjectBase add(XStorageObjectBase xobj)
        {
            XStorageObjectBase xobjExists = (XStorageObjectBase)m_objects[xobj];

            if (xobjExists == null)
            {
                m_objects.Add(xobj, xobj);
                xobjExists = xobj;
            }
            else
            {
                xobjExists.Merge(xobj);
            }
            return(xobjExists);
        }
Exemple #8
0
        private void createObjectsFromLinks(XStorageObjectBase xobj)
        {
            // TODO: Здесь вопрос: удаленные объекты могут содержать линки с ссылками и, если да, то надо ли их обрабатывать ?
            if (xobj is XStorageObjectToDelete)
            {
                return;
            }
            XStorageObjectToSave xobjSave = (XStorageObjectToSave)xobj;

            foreach (DictionaryEntry entry in xobjSave.GetPropsByCapacity(XPropCapacity.Link, XPropCapacity.LinkScalar))
            {
                Guid[] valueOIDs = (Guid[])entry.Value;
                if (valueOIDs.Length == 0)
                {
                    continue;
                }
                string sPropName             = (string)entry.Key;
                XPropInfoObjectLink propInfo = (XPropInfoObjectLink)xobj.TypeInfo.GetProp(sPropName);

                int nIndex = 0;
                foreach (Guid valueOID in valueOIDs)
                {
                    XStorageObjectBase xobjValue = new XStorageObjectToSave(propInfo.ReferedType, valueOID, -1, false);
                    xobjValue.Props[propInfo.ReverseProp.Name] = xobj.ObjectID;
                    // пометим свойство специальным атрибутом, чтобы для него не выполнялась проверка на совпадение содержимого при мердже
                    xobjValue.SetPropMergeMode(propInfo.ReverseProp.Name, XStorageObjectPropMergeModes.Weak);
                    xobjValue = add(xobjValue);
                    // упорядоченный линк ? - установим индексное свойство
                    if (propInfo.OrderByProp != null)
                    {
                        xobjValue.Props[propInfo.OrderByProp.Name] = nIndex++;
                        // пометим свойство специальным атрибутом, говорящим о том что при Merge'е данное значение затрет другое значение
                        xobjValue.SetPropMergeMode(propInfo.OrderByProp.Name, XStorageObjectPropMergeModes.Replace);
                    }
                }
            }
        }
Exemple #9
0
        private void checkReverseProps()
        {
            foreach (XStorageObjectBase xobj in m_objects)
            {
                if (xobj is XStorageObjectToSave)
                {
                    foreach (DictionaryEntry entry in ((XStorageObjectToSave)xobj).GetPropsByCapacity(XPropCapacity.CollectionMembership /*, XPropCapacity.Link, XPropCapacity.LinkScalar*/))
                    {
                        string sPropName = (string)entry.Key;
                        Guid[] valueOIDs = (Guid[])entry.Value;
                        if (valueOIDs.Length == 0)
                        {
                            continue;
                        }
                        XPropInfoObject propInfo = (XPropInfoObject)xobj.TypeInfo.GetProp(sPropName);
                        bool            bError   = false;
                        foreach (Guid valueOID in valueOIDs)
                        {
                            XStorageObjectBase xobjValue = (XStorageObjectBase)m_objectsDictionary[valueOID];
                            if (xobjValue == null)
                            {
                                continue;
                            }
                            // владелец обратного свойства есть в датаграмме

                            if (!xobjValue.Props.Contains(propInfo.ReverseProp.Name))
                            {
                                continue;
                            }
                            // владелец обратного свойства содержит это обратное свойство

                            object vValue = xobjValue.Props[propInfo.ReverseProp.Name];
                            Debug.Assert(vValue != null);
                            if (propInfo.ReverseProp is XPropInfoObjectScalar)
                            {
                                if (vValue == DBNull.Value || (Guid)vValue != xobj.ObjectID)
                                {
                                    bError = true;
                                }
                            }
                            else
                            {
                                // обратное свойство - коллекция, в свойстве массив гидов
                                Guid[] valueOIDsReverse = (Guid[])vValue;
                                // в этом массиве должна быть ссылка на текущий объект (xobj)
                                bool bFound = false;
                                foreach (Guid valueOIDReverse in valueOIDsReverse)
                                {
                                    if (valueOIDReverse == xobj.ObjectID)
                                    {
                                        bFound = true;
                                        break;
                                    }
                                }
                                if (!bFound)
                                {
                                    bError = true;
                                }
                            }
                            if (bError)
                            {
                                throw new XInvalidXmlForestException(
                                          String.Format("Не согласованы свойства объектов: {0}[ID='{1}'], свойство {2} и {3}[ID='{4}'], свойство {5}",
                                                        xobj.ObjectType,                                // 0
                                                        xobj.ObjectID,                                  // 1
                                                        sPropName,                                      // 2
                                                        xobjValue.ObjectType,                           // 3
                                                        xobjValue.ObjectID,                             // 4
                                                        propInfo.ReverseProp.Name                       // 5
                                                        )
                                          );
                            }
                        }
                    }
                }
            }
        }
Exemple #10
0
        private ArrayList normalizeObject(XStorageObjectBase xobj)
        {
            if (xobj is XStorageObjectToDelete)
            {
                return(null);
            }
            XStorageObjectToSave xobjSave    = (XStorageObjectToSave)xobj;
            ArrayList            aNewObjects = null;

            foreach (DictionaryEntry entry in xobjSave.GetPropsByCapacity(XPropCapacity.Link, XPropCapacity.LinkScalar))
            {
                Guid[] valueOIDs = (Guid[])entry.Value;
                if (valueOIDs.Length == 0)
                {
                    continue;
                }
                string sPropName             = (string)entry.Key;
                XPropInfoObjectLink propInfo = (XPropInfoObjectLink)xobj.TypeInfo.GetProp(sPropName);

                int nIndex = 0;
                foreach (Guid valueOID in valueOIDs)
                {
                    XStorageObjectBase xobjValue = (XStorageObjectBase)m_objectsDictionary[valueOID];
                    if (xobjValue == null)
                    {
                        // в датаграмме нет объекта, на который установлена ссылка в линке - значит создадим, этот объект точно не новый
                        xobjValue = new XStorageObjectToSave(propInfo.ReferedType, valueOID, -1, false);
                        if (aNewObjects == null)
                        {
                            aNewObjects = new ArrayList();
                        }
                        aNewObjects.Add(xobjValue);
                        // на случай если данный объект содержится еще в каком-нибудь линке
                        m_objectsDictionary.Add(valueOID, xobjValue);
                    }
                    else
                    {
                        object vValue = xobjValue.Props[propInfo.ReverseProp.Name];
                        if (vValue == null || vValue == DBNull.Value)
                        {
                            // все хорошо - обратное свойство (объектный скаляр) пустое - установим его на текущий объект (xobj)
                            xobjValue.Props[propInfo.ReverseProp.Name] = xobj.ObjectID;
                        }
                        else
                        {
                            Debug.Assert(vValue is Guid);                               // больше ничего другого быть не должно!
                            // обратное свойство уже заполнено, проверим что оно ссылается на текущий объект. если это не так - ругаемся
                            if (((Guid)vValue) != xobj.ObjectID)
                            {
                                throw new XInvalidXmlForestException("Ошибка при установке свойства " + propInfo.ReverseProp.Name + " объекта " + xobjValue.TypeInfo.Name + " [" + xobjValue.ObjectID + "]: нарушение согласованности со свойством " + sPropName + " объекта " + xobj.TypeInfo.Name + " [" + xobj.ObjectID + "]");
                            }
                        }
                    }
                    // упорядоченный линк ? - установим индексное свойство
                    if (propInfo.OrderByProp != null)
                    {
                        xobjValue.Props[propInfo.OrderByProp.Name] = nIndex++;
                    }
                }
            }
            return(aNewObjects);
        }
Exemple #11
0
        private void merge(XStorageObjectBase xobjExists, XStorageObjectBase xobj)
        {
            if (xobjExists.GetType() != xobj.GetType())
            {
                throw new XMergeConflictException("Объект " + xobj.TypeInfo.Name + " [" + xobj.ObjectID + "] присутствует в нескольких несогласованных экземплярах: один помечен delete='1', а другой нет");
            }
            if (xobjExists is XStorageObjectToSave)
            {
                if (((XStorageObjectToSave)xobjExists).IsToInsert != ((XStorageObjectToSave)xobj).IsToInsert)
                {
                    throw new XMergeConflictException("Объект " + xobj.TypeInfo.Name + " [" + xobj.ObjectID + "] присутствует в нескольких несогласованных экземплярах: один помечен new='1', а другой нет ");
                }
            }
            if (xobjExists.TS != xobj.TS && xobjExists.AnalyzeTS && xobj.AnalyzeTS)
            {
                throw new XMergeConflictException("Обнаружены две копии объекта с различающимся ts");
            }

            foreach (DictionaryEntry entry in xobj.Props)
            {
                string sPropName = (string)entry.Key;
                if (!xobjExists.Props.Contains(sPropName))
                {
                    xobjExists.Props.Add(sPropName, entry.Value);
                }
                else
                {
                    bool bNeedScalarCheck = true;
                    // текущее свойство уже есть - если оно массивное, то merge
                    XPropInfoBase propInfo = xobjExists.TypeInfo.GetProp(sPropName);
                    if (propInfo is XPropInfoObject && !(propInfo is XPropInfoObjectScalar))
                    {
                        bNeedScalarCheck = false;
                        XPropCapacity capacity  = ((XPropInfoObject)propInfo).Capacity;
                        Guid[]        valuesOld = (Guid[])xobjExists.Props[sPropName];
                        Guid[]        valuesCur = (Guid[])entry.Value;
                        if (capacity == XPropCapacity.Array || (capacity == XPropCapacity.Link && ((XPropInfoObjectLink)propInfo).OrderByProp != null))
                        {
                            // массивы и упорядоченные линки не подвергаются слиянию - только проверке на совпадение значений
                            if (valuesOld.Length != valuesCur.Length)
                            {
                                throw new XMergeConflictException("Не совпадает количество элементов в свойстве " + sPropName);
                            }
                            for (int i = 0; i < valuesOld.Length; ++i)
                            {
                                if (valuesOld[i] != valuesCur[i])
                                {
                                    throw new XMergeConflictException("Не совпадает значение свойства " + sPropName);
                                }
                            }
                        }
                        else
                        {
                            // коллекция и членство в коллекции
                            ArrayList aValuesNew = new ArrayList(valuesOld.Length + valuesCur.Length);
                            aValuesNew.AddRange(valuesOld);
                            foreach (Guid value in valuesCur)
                            {
                                if (aValuesNew.IndexOf(value) < 0)
                                {
                                    aValuesNew.Add(value);
                                }
                            }

                            Guid[] valuesNew = new Guid[aValuesNew.Count];
                            aValuesNew.CopyTo(valuesNew);
                            xobjExists.Props[sPropName] = valuesNew;
                        }
                    }
                    else if (propInfo is XPropInfoNumeric)
                    {
                        //скалярное - сравним значения, если это не индексное свойство
                        if (((XPropInfoNumeric)propInfo).OrderedLinkProp != null)
                        {
                            bNeedScalarCheck = false;
                        }
                    }
                    if (bNeedScalarCheck)
                    {
                        if (!xobjExists.Props[sPropName].Equals(entry.Value))
                        {
                            throw new XMergeConflictException("Значения свойства " + sPropName + " не совпадают");
                        }
                    }
                }
            }
        }
Exemple #12
0
 /// <summary>
 /// Возвращает ключ под которым объект храниться в словаре
 /// </summary>
 /// <param name="xobj"></param>
 /// <returns>Ключ для хранения в словаре</returns>
 protected string getKey(XStorageObjectBase xobj)
 {
     return(xobj.ObjectType + ":" + xobj.ObjectID);
 }
Exemple #13
0
 public XStorageObjectCollectionSimpleEnumerator(XStorageObjectCollection collection)
 {
     m_collection     = collection;
     m_version        = collection.m_version;
     m_currentElement = null;
 }