예제 #1
0
        /// <summary>
        /// »змен¤ет помеченные свойства объекта, добав뤤 к ним подпись
        /// </summary>
        /// <param name="xobj">текущий объект</param>
        /// <param name="signature">подпись</param>
        private void modifyObjectProps(DomainObjectData xobj, string signature)
        {
            // пройдемс¤ по всем свойствам объекта
            foreach (string sPropName in xobj.UpdatedPropNames)
            {
                // получим информацию о свойстве по его названию
                XPropInfoBase propInfo = xobj.TypeInfo.GetProp(sPropName);

                // если подпись дл¤ данного свойства не нужна, пропускаем его
                if (hasPropSignature(propInfo))
                {
                    object vPropValue = xobj.GetUpdatedPropValue(sPropName);
                    if (vPropValue != null && vPropValue != DBNull.Value)
                    {
                        string sText = null;
                        if (propInfo.VarType == XPropType.vt_string || propInfo.VarType == XPropType.vt_text)
                        {
                            sText = (string)vPropValue;
                        }
                        else
                        {
                            throw new ApplicationException("ћеханизм автоподписи применим только к строковым и текстовым пол¤м");
                        }

                        if (sText != null)
                        {
                            xobj.SetUpdatedPropValue(sPropName, addSignature(sText, signature));
                        }
                    }
                }
            }
        }
예제 #2
0
파일: XDatagram.cs 프로젝트: SanSay157/IT8
        public XStorageObjectBase createXStorageObject(DomainObjectData obj)
        {
            XStorageObjectBase xobj;
            object             vPropValue;

            if (obj.ToDelete)
            {
                xobj = new XStorageObjectToDelete(obj.TypeInfo, obj.ObjectID, obj.TS, true);
            }
            else
            {
                xobj = new XStorageObjectToSave(obj.TypeInfo, obj.ObjectID, obj.TS, obj.IsNew);
                ((XStorageObjectToSave)xobj).PropertiesWithChunkedData = obj.PropertiesWithChunkedData;
            }
            bool bNeedTrackUniqueIndexParticipation = xobj.TypeInfo.HasUniqueIndexes && xobj.TypeInfo.DeferrableIndexes && !obj.ToDelete;

            foreach (string sPropName in obj.UpdatedPropNames)
            {
                vPropValue = obj.GetUpdatedPropValue(sPropName);
                XPropInfoBase propInfo = obj.TypeInfo.GetProp(sPropName);
                if (propInfo is XPropInfoNumeric)
                {
                    if (((XPropInfoSimpleEnumerable)propInfo).IsEnum)
                    {
                        // в качестве значения свойства может быть поcле перечисления, надо привести его в элементарному типу
                        if (vPropValue.GetType().IsEnum)
                        {
                            if (propInfo.VarType == XPropType.vt_i4)
                            {
                                vPropValue = (Int32)vPropValue;
                            }
                            else if (propInfo.VarType == XPropType.vt_i2)
                            {
                                vPropValue = (Int16)vPropValue;
                            }
                            else                             // if (propInfo.VarType == XPropType.vt_ui1)
                            {
                                vPropValue = (byte)vPropValue;
                            }
                        }
                    }
                }
                if (vPropValue != null)
                {
                    xobj.Props[sPropName] = vPropValue;
                }
                // если свойство участвует в уникальном индексе, запомним это
                if (bNeedTrackUniqueIndexParticipation)
                {
                    if (xobj.TypeInfo.IsPropIncludedIntoUniqueIndex(sPropName))
                    {
                        ((XStorageObjectToSave)xobj).ParticipateInUniqueIndex = true;
                    }
                }
            }
            return(xobj);
        }
예제 #3
0
        protected string getObjectValueTypeName(string sObjectType, string sPropName, XStorageConnection con)
        {
            XPropInfoBase xprop_base = con.MetadataManager.GetTypeInfo(sObjectType).GetProp(sPropName);

            if (!(xprop_base is XPropInfoObject))
            {
                throw new ArgumentException("Поддерживаются только объектные свойства");
            }
            return(((XPropInfoObject)xprop_base).ReferedType.Name);
        }
예제 #4
0
        protected DomainPropObjectBase getReverseProp(DomainObject obj)
        {
            XPropInfoBase xprop = PropInfo.ReverseProp;

            if (xprop != null)
            {
                // задано обратное свойства
                return((DomainPropObjectBase)obj.Props[xprop.Name]);
            }
            return(null);
        }
예제 #5
0
        /// <summary>
        /// ѕровер¤ет, должно ли свойство иметь подпись
        /// </summary>
        /// <param name="propInfo">метаданные свойства</param>
        /// <returns>true - свойство должно иметь подпись</returns>
        private bool hasPropSignature(XPropInfoBase propInfo)
        {
            // если свойство не текстовое, подпись не нужна
            if (propInfo.VarType != XPropType.vt_string &&
                propInfo.VarType != XPropType.vt_text)
            {
                return(false);
            }

            // если свойство содержит элемент auto-signature, равный true,
            // то подпись нужна
            if (propInfo.SelectSingleNode("itds:auto-signature[.='true']") != null)
            {
                return(true);
            }

            // иначе подпись не нужна
            return(false);
        }
예제 #6
0
        private static object getPropValue(XmlElement xmlProp, XPropInfoBase propInfo)
        {
            object propValue;

            if (propInfo is XPropInfoObjectScalar)
            {
                if (!xmlProp.HasChildNodes)
                {
                    propValue = DBNull.Value;
                }
                else
                {
                    propValue = new Guid(xmlProp.FirstChild.Attributes["oid"].Value);
                }
            }
            else if (propInfo is IXPropInfoScalar)
            {
                // скалярное необъектное свойство
                propValue = XmlPropValueReader.GetTypedValueFromXml(xmlProp, propInfo.VarType);
                //				if (propInfo.VarType == XPropType.vt_bin || propInfo.VarType == XPropType.vt_text)
                //					propValue = XStorageLOBPropHandle.Create(propInfo.VarType, propValue);
                //else
                if (propValue == null)
                {
                    propValue = DBNull.Value;
                }
            }
            else
            {
                // массивное объектное свойство
                XmlNodeList xmlChildren = xmlProp.SelectNodes("*");
                Guid[]      oids        = new Guid[xmlChildren.Count];
                int         i           = -1;
                foreach (XmlElement xmlChildObj in xmlChildren)
                {
                    oids[++i] = new Guid(xmlChildObj.GetAttribute("oid"));
                }
                propValue = oids;
                //propValue = new XStorageObjectArrayPropHandle(oids);
            }
            return(propValue);
        }
예제 #7
0
        /// <summary>
        /// Записывает данные LOB-свойства
        /// </summary>
        /// <param name="xobj">объект-владелец свойства</param>
        /// <param name="xmlProp">xml-свойство</param>
        /// <param name="propInfo">описание свойства</param>
        private void writeLOBProp(DomainObjectData xobj, XmlElement xmlProp, XPropInfoBase propInfo)
        {
            string    sPropName = propInfo.Name;
            XPropType vt        = propInfo.VarType;
            object    vPropValue;
            int       nDataSize = 0;

            if (xobj.IsNew)
            {
                vPropValue = xobj.GetUpdatedPropValue(sPropName);
                if (vPropValue == null || vPropValue == DBNull.Value)
                {
                    nDataSize = 0;
                }
                else
                {
                    xmlProp.InnerText = XmlPropValueWriter.GetXmlTypedValue(vPropValue, vt);
                }
            }
            else
            {
                nDataSize = xobj.GetLoadedPropDataSize(sPropName);
                if (nDataSize > 0)
                {
                    vPropValue = xobj.GetLoadedPropValue(sPropName);
                    if (vPropValue == null)
                    {
                        // данные в свойстве есть, но не загружены
                        xmlProp.SetAttribute("loaded", "0");
                    }
                    else
                    {
                        xmlProp.InnerText = XmlPropValueWriter.GetXmlTypedValue(vPropValue, vt);
                    }
                }
            }
            xmlProp.SetAttribute("data-size", XmlConvert.ToString(nDataSize));
        }
예제 #8
0
 public DomainPropLOB(DomainObject objParent, XPropInfoBase xpropInfo) : base(objParent, xpropInfo)
 {
     m_state = DomainPropLoadableState.Ghost;
 }
예제 #9
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 + " не совпадают");
                        }
                    }
                }
            }
        }
예제 #10
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);
        }
예제 #11
0
        /// <summary>
        /// Формирует заготовку команды update для переданного объекта.
        /// Формируется текст ADO-команда, параметры и подсчитывается размер команды.
        /// Имя параметра устанавливается как имя колонки + "t" +  nBatch + "o" + nIndex
        /// Для всех колонок используются параметры (в отличии от createUpdateCommandForSameTypeObjects).
        /// </summary>
        /// <param name="xs">Реализация XStorageConnection</param>
        /// <param name="disp">диспетчер запросов</param>
        /// <param name="xobj">объект, для которого требуется сформировать insert-команду</param>
        /// <param name="nBatchIndex">индекс группы объектов</param>
        /// <param name="nIndex">индекс объекта в списке</param>
        /// <param name="cmd">команда, как фабрика параметров</param>
        /// <param name="bSuppressMagicBit">признак того, что надо исключить обработку поля MagicBit.
        /// Если передан false, то в команде insert добавляется поле MagicBit устанавливаемое в 1.
        /// Если передан true, то в команде insert поле MagicBit не участвует.
        /// </param>
        /// <returns>заготовка команды с оператором UPDATE всех объектов из списка, либо null</returns>
        protected bool updateObject(XStorageConnection xs, XDbStatementDispatcher disp, XStorageObjectToSave xobj, int nBatchIndex, int nIndex, XDbCommand cmd, bool bSuppressMagicBit)
        {
            StringBuilder       cmdBuilder;                              // построитель текста одной команды update
            string              sPropName;                               // наименование свойства, колонки и параметра
            string              sParamName;                              // наименование параметра команды
            object              vValue;                                  // значение свойства
            List <XDbParameter> aParameters = new List <XDbParameter>(); // коллекция параметров формируемой команды
            bool bCmdConstructed            = false;                     // признак того, что команда update сформирована

            cmdBuilder = new StringBuilder();
            cmdBuilder.AppendFormat("UPDATE {0} SET ",
                                    xs.GetTableQName(xobj.SchemaName, xobj.ObjectType));
            if (xobj.UpdateTS)
            {
                cmdBuilder.AppendFormat("{0} = CASE WHEN {0}<{1} THEN {0}+1 ELSE 1 END{2}",
                                        xs.ArrangeSqlName("ts"),        // 0
                                        Int64.MaxValue,                 // 1
                                        xs.Behavior.SqlNewLine);        // 2
                bCmdConstructed = true;
            }
            foreach (DictionaryEntry propDesc in xobj.Props)
            {
                sPropName = (String)propDesc.Key;
                vValue    = propDesc.Value;
                XPropInfoBase propInfo = xobj.TypeInfo.GetProp(sPropName);
                if (!(propInfo is IXPropInfoScalar))
                {
                    continue;
                }
                if ((propInfo.VarType == XPropType.vt_bin || propInfo.VarType == XPropType.vt_text) /*&& vValue != DBNull.Value */)
                {
                    continue;
                }
                if (bCmdConstructed)
                {
                    cmdBuilder.Append(",");                             // текущая колонка уже не первая - добавим запятую
                }
                bCmdConstructed = true;
                xobj.TypeInfo.CheckPropValue(sPropName, propInfo.VarType, vValue);
                sParamName = xs.GetParameterName(String.Format("{0}t{1}o{2}", sPropName, nBatchIndex, nIndex));
                cmdBuilder.Append(xs.ArrangeSqlName(sPropName) + "=" + sParamName + xs.Behavior.SqlNewLine);
                aParameters.Add(cmd.CreateParameter(sParamName, propInfo.VarType, ParameterDirection.Input, true, vValue));
            }

            if (!bCmdConstructed)
            {
                return(false);
            }
            // если объект участвует в уникальных индексах и есть объекты в списках на вставку и/или удаление, то
            // установим MagicBit в 1 для предотвражения нарушения уникальных индексов
            if (!bSuppressMagicBit && xobj.ParticipateInUniqueIndex)
            {
                xobj.MagicBitAffected = true;
                cmdBuilder.AppendFormat(", {0}=1", xs.ArrangeSqlName("MagicBit"));
            }
            // сформируем условие WHERE: (ObjectID={@oid} AND ts={@ts}),
            // однако условие AND ts={@ts} добавим только если у объекта установлен признак AnalizeTS
            cmdBuilder.Append(" WHERE ");
            sParamName = xs.GetParameterName(String.Format("{0}t{1}o{2}", "ObjectID", nBatchIndex, nIndex));
            cmdBuilder.AppendFormat("({0}={1}",
                                    xs.ArrangeSqlName("ObjectID"),
                                    sParamName);
            aParameters.Add(cmd.CreateParameter(sParamName, DbType.Guid, ParameterDirection.Input, true, xobj.ObjectID));
            if (xobj.AnalyzeTS)
            {
                sParamName = xs.GetParameterName(String.Format("{0}t{1}o{2}", "ts", nBatchIndex, nIndex));
                cmdBuilder.AppendFormat(" AND {0}={1}",
                                        xs.ArrangeSqlName("ts"),        // 0
                                        sParamName);                    // 1
                aParameters.Add(cmd.CreateParameter(sParamName, DbType.Int64, ParameterDirection.Input, true, xobj.TS));
            }
            cmdBuilder.Append(")");

            disp.DispatchStatement(cmdBuilder.ToString(), aParameters, true);
            return(true);
        }
예제 #12
0
파일: UnitOfWork.cs 프로젝트: SanSay157/IT8
        protected virtual DomainPropBase createPropInstace(DomainObject obj, XPropInfoBase xpropInfo)
        {
            DomainPropBase prop;

            switch (xpropInfo.VarType)
            {
            case XPropType.vt_object:
                if (xpropInfo is XPropInfoObjectScalar)
                {
                    prop = new DomainPropObjectScalar(obj, (XPropInfoObject)xpropInfo);
                }
                else if (xpropInfo is XPropInfoObjectArray)
                {
                    prop = new DomainPropCollection(obj, (XPropInfoObjectArray)xpropInfo);
                }
                else if (xpropInfo is XPropInfoObjectLink)
                {
                    prop = new DomainPropLink(obj, (XPropInfoObjectLink)xpropInfo);
                }
                else
                {
                    throw new ApplicationException();
                }
                break;

            case XPropType.vt_text:
                prop = new DomainPropText(obj, xpropInfo);
                break;

            case XPropType.vt_bin:
                prop = new DomainPropBinary(obj, xpropInfo);
                break;

            case XPropType.vt_boolean:
                prop = new DomainPropBoolean(obj, (XPropInfoBoolean)xpropInfo);
                break;

            case XPropType.vt_string:
                prop = new DomainPropString(obj, (XPropInfoString)xpropInfo);
                break;

            case XPropType.vt_uuid:
                prop = new DomainPropUUID(obj, (XPropInfoSimple)xpropInfo);
                break;

            case XPropType.vt_smallBin:
                prop = new DomainPropSmallBin(obj, (XPropInfoSmallBin)xpropInfo);
                break;

            case XPropType.vt_r4:
                prop = new DomainPropNumericSingle(obj, (XPropInfoNumeric)xpropInfo);
                break;

            case XPropType.vt_r8:
                prop = new DomainPropNumericDouble(obj, (XPropInfoNumeric)xpropInfo);
                break;

            case XPropType.vt_fixed:
                prop = new DomainPropNumericDecimal(obj, (XPropInfoNumeric)xpropInfo);
                break;

            default:
                if (xpropInfo is XPropInfoNumeric)
                {
                    prop = new DomainPropNumericInt(obj, (XPropInfoNumeric)xpropInfo);
                }
                else if (xpropInfo is XPropInfoDatetime)
                {
                    prop = new DomainPropDateTime(obj, (XPropInfoDatetime)xpropInfo);
                }
                else
                {
                    throw new ApplicationException();
                }
                break;
            }
            return(prop);
        }
예제 #13
0
파일: UnitOfWork.cs 프로젝트: SanSay157/IT8
        internal void deleteObject(DomainObject obj)
        {
            OnDeletingObject(new DeletingObjectEventArgs(obj));
            // Сформируем список ссылок и список обязательных ссылок на текущий объект
            ArrayList aReferences          = new ArrayList();
            ArrayList aMandatoryReferences = new ArrayList();

            // по всем свойствам Скаляр, Массив, Коллекция, ссылающиймся на тип текущего объекта
            foreach (XPropInfoObject propInfo in obj.TypeInfo.ReferencesOnMe)
            {
                // по всем объектам реестра, обладающим текущим свойством
                foreach (DomainObject objRef in m_objects.GetSameTypeObjects(propInfo.ParentType.Name).Values)
                {
                    // ссылки со стороны заглушек и инвалиндых объектов нам не интересны
                    if (!objRef.IsLoaded && !objRef.IsNew)
                    {
                        continue;
                    }
                    DomainPropBase prop = (DomainPropBase)objRef.Props[propInfo.Name];
                    if (prop == null)
                    {
                        continue;
                    }

                    if (prop is DomainPropObjectScalar)
                    {
                        DomainPropObjectScalar propScalar = (DomainPropObjectScalar)prop;
                        if (propScalar.HasReferedOn(obj.ObjectID))
                        {
                            aReferences.Add(propScalar);
                            if (propScalar.PropInfo.NotNull)
                            {
                                aMandatoryReferences.Add(propScalar);
                            }
                        }
                    }
                    else if (prop is DomainPropCollectionBase)
                    {
                        DomainPropCollectionBase propCol = (DomainPropCollectionBase)prop;
                        if (propCol.FindObjectValue(obj.ObjectID) != null)
                        {
                            aReferences.Add(prop);
                            // если массив или коллекция без обратного свойства, значит свойство обязательное
                            if (!(propCol.PropInfo.Capacity == XPropCapacity.Collection && propCol.PropInfo.ReverseProp == null))
                            {
                                aMandatoryReferences.Add(prop);
                            }
                        }
                    }
                }
            }
            if (aReferences.Count > 0)
            {
                if (OnDeleteObjectConflict(new DeleteObjectConflictEventArgs(obj, aReferences, aMandatoryReferences)))
                {
                    // TODO: а что делать дальше???
                    return;
                }
                else
                {
                    throw new InvalidOperationException("Объект " + obj.ObjectType + " [" + obj.ObjectID.ToString() + "] не может быть удален, т.к. на него имеются обязательные ссылки");
                }
            }

            // раз объект можно удалять, вычистим ссылки на него из линков, членств в коллекции и массиве
            foreach (DomainPropBase prop in obj.Props.Values)
            {
                if (prop is DomainPropObjectBase)
                {
                    XPropInfoBase revPropInfo = ((DomainPropObjectBase)prop).PropInfo.ReverseProp;
                    // синхронизируем "слабые" обратные свойства, т.е. удалим ссылки на текущий объект
                    if (revPropInfo != null)
                    {
                        if (prop is DomainPropObjectScalar)
                        {
                            // удалим текущий объект из обратного линка
                            DomainPropObjectScalar propScalar = (DomainPropObjectScalar)prop;
                            if (!propScalar.IsNull)
                            {
                                ((DomainPropLink)propScalar.Value.Props[revPropInfo.Name]).internal_AddPendingAction(DomainPropPendingActionMode.Remove, obj);
                            }
                        }
                        else if (prop is DomainPropArray || prop is DomainPropCollection)
                        {
                            // удалим текущий объект из обратного членства в массиве или членства в коллекции
                            DomainPropCollectionBase propArray = (DomainPropCollectionBase)prop;
                            foreach (DomainObject objValue in propArray.Internal_Values)
                            {
                                ((DomainPropCollectionBase)objValue.Props[revPropInfo.Name]).internal_AddPendingAction(DomainPropPendingActionMode.Remove, obj);
                            }
                        }
                    }
                }
            }
            if (obj.IsNew)
            {
                m_objects.Remove(obj);
            }
            obj.setDeleted();
        }
예제 #14
0
 public DomainPropObjectBase(DomainObject obj, XPropInfoBase xpropInfo)
     : base(obj, xpropInfo)
 {
 }
예제 #15
0
 public DomainPropText(DomainObject objParent, XPropInfoBase xpropInfo)
     : base(objParent, xpropInfo)
 {
 }
예제 #16
0
 public DomainPropBase(DomainObject obj, XPropInfoBase xpropInfo)
 {
     m_objParent = obj;
     m_xpropInfo = xpropInfo;
 }
예제 #17
0
        /// <summary>
        /// Формирует заготовку команды insert для переданного объекта.
        /// Формирутеся текст ADO-команда, параметры и подсчитывается размер команды.
        /// Имя параметра устанавливается как имя колонки + индекс объекта в общем списке
        /// </summary>
        /// <param name="xs">Реализация XStorageConnection</param>
        /// <param name="disp">диспетчер запросов</param>
        /// <param name="xobj">объект, для которого требуется сформировать insert-команду</param>
        /// <param name="cmd">команда</param>
        /// <param name="nIndex">индекс объекта в списке</param>
        /// <param name="bSuppressMagicBit">признак того, что надо исключить обработку поля MagicBit.
        /// Если передан false, то в команде insert добавляется поле MagicBit устанавливаемое в 1.
        /// Если передан true, то в команде insert поле MagicBit не участвует.
        /// </param>
        protected void insertObject(XStorageConnection xs, XDbStatementDispatcher disp, XStorageObjectToSave xobj, XDbCommand cmd, int nIndex, bool bSuppressMagicBit)
        {
            StringBuilder queryBuilder  = new StringBuilder();  // построитель отдельного insert'a
            StringBuilder valuesBuilder = new StringBuilder();  // построитель списка значений
            string        sPropName;                            // наименование свойства, колонки и параметра
            string        sParamName;                           // наименование параметра команды
            object        vValue;                               // значение свойства


            List <XDbParameter> Params = new List <XDbParameter>();

            queryBuilder.AppendFormat("INSERT INTO {0} ({1}, {2}",
                                      xs.GetTableQName(xobj.SchemaName, xobj.ObjectType), // 0
                                      xs.ArrangeSqlName("ObjectID"),                      // 1
                                      xs.ArrangeSqlName("ts")                             // 2
                                      );
            // установим значения ObjectID, ts (в качастве ts установим 1)
            valuesBuilder.Append(xs.ArrangeSqlGuid(xobj.ObjectID) + ",1");
            // если не запрещено, то значение MagicBit = 1
            if (!bSuppressMagicBit && xobj.ParticipateInUniqueIndex)
            {
                queryBuilder.AppendFormat(",{0}", xs.ArrangeSqlName("MagicBit"));
                xobj.MagicBitAffected = true;
                valuesBuilder.Append(",1");
            }
            foreach (DictionaryEntry propDesc in xobj.Props)
            {
                sPropName = (String)propDesc.Key;
                vValue    = propDesc.Value;
                if (vValue == null)
                {
                    continue;
                }
                XPropInfoBase propInfo = xobj.TypeInfo.GetProp(sPropName);
                if (!(propInfo is IXPropInfoScalar))
                {
                    continue;
                }
                if ((propInfo.VarType == XPropType.vt_bin || propInfo.VarType == XPropType.vt_text) /* && vValue != DBNull.Value*/)
                {
                    continue;
                }
                xobj.TypeInfo.CheckPropValue(sPropName, propInfo.VarType, vValue);
                if (vValue != DBNull.Value)
                {
                    queryBuilder.Append(',');
                    queryBuilder.Append(xs.ArrangeSqlName(sPropName));
                    valuesBuilder.Append(',');
                    if (xs.DangerXmlTypes.ContainsKey(propInfo.VarType))
                    {
                        // сформируем наименование параметра (без префикса) как имя колонки + "o" + переданный индекс
                        sParamName = xs.GetParameterName(sPropName + "o" + nIndex);
                        Params.Add(cmd.CreateParameter(sParamName, propInfo.VarType, ParameterDirection.Input, false, vValue));
                        valuesBuilder.Append(sParamName);
                    }
                    else
                    {
                        valuesBuilder.Append(xs.ArrangeSqlValue(vValue, propInfo.VarType));
                    }
                }
            }
            // сформируем команду и добавим ее в общий батч
            queryBuilder.AppendFormat(") values ({0})", valuesBuilder.ToString());
            disp.DispatchStatement(queryBuilder.ToString(), Params, false);
        }
예제 #18
0
        private void checkAndSyncReverseProps(DomainObjectDataSet dataSet)
        {
            IEnumerator enumerator = dataSet.GetModifiedObjectsEnumerator(true);
            object      vPropValue;

            while (enumerator.MoveNext())
            {
                DomainObjectData xobj = (DomainObjectData)enumerator.Current;
                foreach (string sPropName in xobj.UpdatedPropNames)
                {
                    XPropInfoBase propInfo = xobj.TypeInfo.GetProp(sPropName);
                    Debug.Assert(propInfo != null);
                    if (propInfo.VarType != XPropType.vt_object)
                    {
                        continue;
                    }

                    XPropInfoObject propInfoObj = (XPropInfoObject)propInfo;
                    if (propInfoObj.Capacity == XPropCapacity.CollectionMembership || propInfoObj.Capacity == XPropCapacity.Link)
                    {
                        Guid[] values = (Guid[])xobj.GetUpdatedPropValue(sPropName);
                        if (values.Length > 0)
                        {
                            foreach (Guid valueObjectID in values)
                            {
                                bool             bError    = false;
                                DomainObjectData xobjValue = dataSet.Find(propInfoObj.ReferedType.Name, valueObjectID);
                                // объект-значение объектного свойства sPropName есть в контексте и он будет сохраняться
                                if (xobjValue != null && xobjValue.HasNewData)
                                {
                                    // если текущее свойство "членство в коллекции" и в объекте-значении есть обратное свойство (коллекция),
                                    // проверим, что обратное свойство содержит ссылку на текущий объект (xobj)
                                    if (propInfoObj.Capacity == XPropCapacity.CollectionMembership && xobjValue.HasUpdatedProp(propInfoObj.ReverseProp.Name))
                                    {
                                        Guid[] propRevValues = (Guid[])xobjValue.GetUpdatedPropValue(propInfoObj.ReverseProp.Name);
                                        Debug.Assert(propRevValues != null);
                                        // если обратное свойство (коллекция) не содержит ссылку на текущий объект - исключение
                                        if (Array.IndexOf(propRevValues, xobj.ObjectID) == -1)
                                        {
                                            bError = true;
                                        }
                                    }
                                    // если текущее свойство линк, то установим обратное свойство - объектный скаляр
                                    else if (propInfoObj.Capacity == XPropCapacity.Link)
                                    {
                                        vPropValue = xobjValue.GetUpdatedPropValue(propInfoObj.ReverseProp.Name);
                                        // если обратное свойство (скаляр) установлено, то проверим, что оно ссылается на текущий объект
                                        if (vPropValue != null)
                                        {
                                            Debug.Assert(vPropValue is Guid);
                                            if ((vPropValue is DBNull) || ((Guid)vPropValue) != xobj.ObjectID)
                                            {
                                                bError = true;
                                            }
                                        }
                                        // обратное свойство неустановлено - установим его на текущий объект
                                        else
                                        {
                                            xobjValue.SetUpdatedPropValue(propInfoObj.ReverseProp.Name, xobj.ObjectID);
                                        }
                                    }
                                    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
                                                                propInfoObj.ReverseProp.Name                                    // 5
                                                                ));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #19
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);
        }
예제 #20
0
        private void serializePropertyInternal(DomainObjectData xobj, XmlElement xmlProp, PreloadsNavigator nav)
        {
            DomainObjectDataSet dataSet = xobj.Context;
            string sPropName;
            object vPropValue;

            sPropName = xmlProp.LocalName;
            XPropInfoBase propInfo = xobj.TypeInfo.GetProp(sPropName);

            switch (propInfo.VarType)
            {
            case XPropType.vt_bin:
            case XPropType.vt_text:
                writeLOBProp(xobj, xmlProp, propInfo);
                break;

            case XPropType.vt_object:
                if (propInfo is XPropInfoObjectScalar)
                {
                    // скалярное свойство
                    if (xobj.IsNew)
                    {
                        vPropValue = xobj.GetUpdatedPropValue(sPropName);
                    }
                    else
                    {
                        vPropValue = xobj.GetLoadedPropValue(sPropName);
                    }

                    if (vPropValue != null && !(vPropValue is DBNull))
                    {
                        addValueIntoObjectProp(dataSet, xmlProp, (XPropInfoObjectScalar)propInfo, (Guid)vPropValue, nav);
                    }
                }
                else
                {
                    // массивное свойство
                    if (xobj.IsNew)
                    {
                        vPropValue = xobj.GetUpdatedPropValue(sPropName);
                    }
                    else
                    {
                        vPropValue = xobj.GetLoadedPropValue(sPropName);
                    }

                    writeArrayProp(xobj, xmlProp, vPropValue, (XPropInfoObject)propInfo, nav);
                }
                break;

            default:
                if (xobj.IsNew)
                {
                    vPropValue = xobj.GetUpdatedPropValue(sPropName);
                }
                else
                {
                    vPropValue = xobj.GetLoadedPropValue(sPropName);
                }

                if (vPropValue != null && !(vPropValue is DBNull))
                {
                    xmlProp.InnerText = XmlPropValueWriter.GetXmlTypedValue(vPropValue, propInfo.VarType);
                }
                else
                {
                    xmlProp.InnerText = String.Empty;
                }
                break;
            }
        }