Exemplo n.º 1
0
        public static XStorageObjectBase CreateXStorageObject(XmlElement xmlObject, XTypeInfo typeInfo)
        {
            XStorageObjectBase xobj;
            Guid  oid = new Guid(xmlObject.GetAttribute("oid"));
            Int64 nTS;

            if (xmlObject.HasAttribute("ts"))
            {
                nTS = Int32.Parse(xmlObject.GetAttribute("ts"));
            }
            else
            {
                nTS = -1;
            }
            bool bIsNew = false;

            if (xmlObject.HasAttribute("delete"))
            {
                xobj = new XStorageObjectToDelete(typeInfo, oid, nTS, true);
            }
            else
            {
                bIsNew = xmlObject.HasAttribute("new");
                xobj   = new XStorageObjectToSave(typeInfo, oid, nTS, bIsNew);
            }
            bool bNeedTrackUniqueIndexParticipation = typeInfo.HasUniqueIndexes && typeInfo.DeferrableIndexes && xobj is XStorageObjectToSave;

            // по всем свойствам без признака loaded="0"
            foreach (XmlElement xmlProp in xmlObject.SelectNodes("*[not(@loaded)]"))
            {
                XPropInfoBase xprop = typeInfo.GetProp(xmlProp.LocalName);
                if (xprop == null)
                {
                    continue;
                }
                // если на xml-свойстве неудаляемого объекта есть атрибут с идентификатором цепочки кусочных данных, то занесем его в специальный словарь
                if (xobj is XStorageObjectToSave && xmlProp.HasAttribute(ATTR_CHUNCK_CHAIN_ID))
                {
                    ((XStorageObjectToSave)xobj).PropertiesWithChunkedData.Add(xprop.Name, new Guid(xmlProp.GetAttribute(ATTR_CHUNCK_CHAIN_ID)));
                }
                // членство в массиве проигнорируем
                if (xprop is XPropInfoObjectArray)
                {
                    if (((XPropInfoObjectArray)xprop).Capacity == XPropCapacity.ArrayMembership)
                    {
                        continue;
                    }
                }
                // пустые массивные свойства новых объектов проигнорируем
                if (bIsNew)
                {
                    if (xprop is XPropInfoObjectArray || xprop is XPropInfoObjectLink)
                    {
                        if (!xmlProp.HasChildNodes)
                        {
                            continue;
                        }
                    }
                }
                xobj.Props.Add(xprop.Name, getPropValue(xmlProp, xprop));
                // если свойство участвует в уникальном индексе, запомним это
                if (bNeedTrackUniqueIndexParticipation)
                {
                    if (typeInfo.IsPropIncludedIntoUniqueIndex(xprop.Name))
                    {
                        ((XStorageObjectToSave)xobj).ParticipateInUniqueIndex = true;
                    }
                }
            }
            return(xobj);
        }
Exemplo n.º 2
0
        private DomainObjectData DeserializeObject(XmlElement xmlObject, XTypeInfo typeInfo, DomainObjectDataSet dataSet)
        {
            DomainObjectData xobj;
            Guid             oid        = new Guid(xmlObject.GetAttribute("oid"));
            bool             bIsNew     = xmlObject.HasAttribute("new");
            bool             bToDelete  = xmlObject.HasAttribute("delete");
            bool             bNeedMerge = false;
            object           vPropValue;

            xobj = dataSet.Find(typeInfo.Name, oid);
            if (xobj == null)
            {
                // такого объекта нет в множестве: создадим его и добавить
                if (bToDelete)
                {
                    xobj = dataSet.CreateToDelete(typeInfo.Name, oid);
                }
                else
                {
                    bIsNew = xmlObject.HasAttribute("new");
                    xobj   = dataSet.CreateStub(typeInfo.Name, oid, bIsNew);
                }
            }
            else
            {
                // объект уже присутствует
                if (bIsNew != xobj.IsNew)
                {
                    throw new XMergeConflictException("Объект " + xobj.TypeInfo.Name + " [" + xobj.ObjectID + "] присутствует в нескольких несогласованных экземплярах: один помечен new='1', а другой нет ");
                }
                if (bToDelete != xobj.ToDelete)
                {
                    throw new XMergeConflictException("Объект " + xobj.TypeInfo.Name + " [" + xobj.ObjectID + "] присутствует в нескольких несогласованных экземплярах: один помечен delete='1', а другой нет ");
                }
                bNeedMerge = true;
            }
            if (xmlObject.HasAttribute("ts"))
            {
                xobj.SetTS(Int64.Parse(xmlObject.GetAttribute("ts")));
            }
            // по всем свойствам без признака loaded="0"
            foreach (XmlElement xmlProp in xmlObject.SelectNodes("*[not(@loaded)]"))
            {
                XPropInfoBase propInfo = typeInfo.GetProp(xmlProp.LocalName);
                // xml-узлы не соответствующие свойствам из МД игнорируем
                if (propInfo == null)
                {
                    continue;
                }

                if (!bToDelete && xmlProp.HasAttribute(XDatagram.ATTR_CHUNCK_CHAIN_ID))
                {
                    xobj.PropertiesWithChunkedData.Add(propInfo.Name, new Guid(xmlProp.GetAttribute(XDatagram.ATTR_CHUNCK_CHAIN_ID)));
                }

                // членство в массиве проигнорируем
                if (propInfo is XPropInfoObjectArray)
                {
                    if (((XPropInfoObjectArray)propInfo).Capacity == XPropCapacity.ArrayMembership)
                    {
                        continue;
                    }
                }
                // пустые массивные свойства новых объектов проигнорируем
                if (bIsNew)
                {
                    if (propInfo is XPropInfoObjectArray || propInfo is XPropInfoObjectLink)
                    {
                        if (!xmlProp.HasChildNodes)
                        {
                            continue;
                        }
                    }
                }
                vPropValue = getPropValue(xmlProp, propInfo);
                if (bNeedMerge && xobj.HasUpdatedProp(propInfo.Name))
                {
                    bool   bNeedScalarCheck = true;
                    object vPropValueExist  = xobj.GetUpdatedPropValue(propInfo.Name);
                    if (propInfo is XPropInfoObject && !(propInfo is XPropInfoObjectScalar))
                    {
                        // объектное массивное свойство
                        bNeedScalarCheck = false;
                        XPropCapacity capacity  = ((XPropInfoObject)propInfo).Capacity;
                        Guid[]        valuesOld = (Guid[])vPropValueExist;
                        Guid[]        valuesCur = (Guid[])vPropValue;
                        if (capacity == XPropCapacity.Array || (capacity == XPropCapacity.Link && ((XPropInfoObjectLink)propInfo).OrderByProp != null))
                        {
                            // массивы и упорядоченные линки не подвергаются слиянию - только проверке на совпадение значений
                            if (valuesOld.Length != valuesCur.Length)
                            {
                                throw new XMergeConflictException("Не совпадает количество элементов в свойстве " + propInfo.Name);
                            }
                            for (int i = 0; i < valuesOld.Length; ++i)
                            {
                                if (valuesOld[i] != valuesCur[i])
                                {
                                    throw new XMergeConflictException("Не совпадает значение свойства " + propInfo.Name);
                                }
                            }
                        }
                        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);
                            vPropValue = valuesNew;
                        }
                    }
                    else if (propInfo is XPropInfoNumeric)
                    {
                        // числовое свойтсво - будем сравнивать значения, если это не индексное свойство линка
                        if (((XPropInfoNumeric)propInfo).OrderedLinkProp != null)
                        {
                            bNeedScalarCheck = false;
                        }
                    }
                    if (bNeedScalarCheck)
                    {
                        // надо сравнить значения скалярного свойства
                        // т.к. Equals - виртуальный метод, то должно работать
                        if (!vPropValueExist.Equals(vPropValue))
                        {
                            throw new XMergeConflictException("Значения свойства " + propInfo.Name + " не совпадают");
                        }
                    }
                }
                xobj.SetUpdatedPropValue(propInfo.Name, vPropValue);
                // Удалено: кусочная загрузка (xmlProp.HasAttribute(ATTR_CHUNCK_CHAIN_ID))
            }
            return(xobj);
        }