예제 #1
0
        /// <summary>
        /// Creates an XmlElement representing an Epi Info 7 view's data.
        /// </summary>
        /// <param name="xmlDataPackage">The data package xml document that the XmlElement should be added to</param>
        /// <param name="form">The form whose data will be serialized</param>
        /// <returns>XmlElement; represents the form's data in Xml format, suitable for use in data packaging</returns>
        protected XmlElement CreateXmlFormDataElement(XmlDocument xmlDataPackage, View form)
        {
            #region Input Validation
            if (xmlDataPackage == null)
            {
                throw new ArgumentNullException("xmlDataPackage");
            }
            if (form == null)
            {
                throw new ArgumentNullException("form");
            }
            #endregion // Input Validation

            XmlElement data = xmlDataPackage.CreateElement("Data");

            if (StatusChanged != null)
            {
                StatusChanged(string.Format(PackagerStrings.GUID_LIST_SETUP, form.Name));
            }
            if (ResetProgress != null)
            {
                ResetProgress();
            }

            /* This seems like an usual set of steps to just iterate over the data. The problem is that we can't "just
             * iterate over the data" - the data is split up page tables, with one table representing one page on the
             * form. While a JOIN might be able to bring everything together into one table, it might not - for example,
             * if there are >255 fields after the JOIN, an OleDb exception will be thrown.
             *
             * To get around this issue: The code first iterates over the rows in the BASE TABLE, obtaining the GUID
             * values for each. The GUIDs and their corresponding XmlElement go into a dictionary.
             *
             * Later, each row in each page is iterated over; as the GUIDs for each page table are accessed, the corresponding
             * XmlElement is pulled from the dictionary. Field data is added to it for each field that has data. In this
             * manner, it doesn't matter that each row is technically accessed out-of-order because they'll still show up
             * in-order in the resulting Xml.
             *
             * Filtering adds another layer of complexity. To filter, a JOIN operation is needed so that the filters can
             * be applied across all those tables, since the fields in the filter may be across different tables. The
             * RowFilter class provides a way to handle this; we simply get the query from that object and apply it to the
             * reader. Only GUIDs that match the filter are added to the dictionary of guids.
             */

            // We need to exclude records from child forms that may now be orphaned as a result of a filter applied to the parent
            if (form.IsRelatedView && PreviousDistanceFromRoot < CurrentDistanceFromRoot)
            {
                ParentIdList.Clear();
                foreach (KeyValuePair <string, XmlElement> kvp in IdList)
                {
                    ParentIdList.Add(kvp.Key);
                }
            }

            IdList.Clear(); // Very important, this needs to be re-set in case we've already processed a form (this is a class level variable)

            if (!ExportInfo.RecordsPackaged.ContainsKey(form))
            {
                ExportInfo.RecordsPackaged.Add(form, 0);
            }

            bool       filterThisForm = false;
            RowFilters filters        = null;
            Query      selectQuery    = null;

            if (Filters != null && Filters.ContainsKey(form.Name) && Filters[form.Name].Count() > 0)
            {
                filterThisForm = true;
                filters        = Filters[form.Name];
                selectQuery    = filters.GetGuidSelectQuery(form);
            }

            double totalRecords = 0;

            using (IDataReader guidReader = filterThisForm ? SourceProject.CollectedData.GetDatabase().ExecuteReader(selectQuery) : SourceProject.CollectedData.GetDatabase().GetTableDataReader(form.TableName))
            {
                while (guidReader.Read())
                {
                    string   guid            = guidReader["GlobalRecordId"].ToString();
                    string   fkey            = guidReader["FKEY"].ToString();
                    string   recstatus       = guidReader["RECSTATUS"].ToString();
                    string   firstSaveUserId = string.Empty;
                    DateTime?firstSaveTime   = null;
                    string   lastSaveUserId  = string.Empty;
                    DateTime?lastSaveTime    = null;

                    if (guidReader.FieldCount > 3)
                    {
                        try
                        {
                            firstSaveUserId = guidReader["FirstSaveLogonName"].ToString();
                            if (guidReader["FirstSaveTime"] != DBNull.Value)
                            {
                                firstSaveTime = (DateTime)guidReader["FirstSaveTime"];
                            }
                            lastSaveUserId = guidReader["LastSaveLogonName"].ToString();
                            if (guidReader["LastSaveTime"] != DBNull.Value)
                            {
                                lastSaveTime = (DateTime)guidReader["LastSaveTime"];
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            // just ignore, probably an older upgraded project
                        }
                    }

                    if (recstatus.Equals("1")) // only include undeleted records
                    {
                        if (!form.IsRelatedView || ParentIdList.Contains(fkey))
                        {
                            XmlElement   record = xmlDataPackage.CreateElement("Record");
                            XmlAttribute id     = xmlDataPackage.CreateAttribute("Id");
                            id.Value = guid;
                            record.Attributes.Append(id);

                            if (!string.IsNullOrEmpty(fkey))
                            {
                                XmlAttribute foreignKey = xmlDataPackage.CreateAttribute("Fkey");
                                foreignKey.Value = fkey;
                                record.Attributes.Append(foreignKey);
                            }
                            if (!string.IsNullOrEmpty(firstSaveUserId))
                            {
                                XmlAttribute firstSaveId = xmlDataPackage.CreateAttribute("FirstSaveUserId");
                                firstSaveId.Value = firstSaveUserId;
                                record.Attributes.Append(firstSaveId);
                            }
                            if (!string.IsNullOrEmpty(lastSaveUserId))
                            {
                                XmlAttribute lastSaveId = xmlDataPackage.CreateAttribute("LastSaveUserId");
                                lastSaveId.Value = lastSaveUserId;
                                record.Attributes.Append(lastSaveId);
                            }
                            if (firstSaveTime.HasValue)
                            {
                                XmlAttribute firstSaveDateTime = xmlDataPackage.CreateAttribute("FirstSaveTime");
                                firstSaveDateTime.Value = firstSaveTime.Value.Ticks.ToString();
                                record.Attributes.Append(firstSaveDateTime);
                            }
                            if (lastSaveTime.HasValue)
                            {
                                XmlAttribute lastSaveDateTime = xmlDataPackage.CreateAttribute("LastSaveTime");
                                lastSaveDateTime.Value = lastSaveTime.Value.Ticks.ToString();
                                record.Attributes.Append(lastSaveDateTime);
                            }
                            IdList.Add(guid, record);
                            totalRecords++;

                            ExportInfo.TotalRecordsPackaged++;
                            ExportInfo.RecordsPackaged[form]++;
                        }
                    }
                }
            }

            totalRecords = totalRecords * form.Pages.Count;
            int processedRecords = 0;

            if (StatusChanged != null)
            {
                StatusChanged(string.Format(PackagerStrings.ADDING_FIELD_DATA, form.Name));
            }

            foreach (Page page in form.Pages)
            {
                using (IDataReader reader = SourceProject.CollectedData.GetDatabase().GetTableDataReader(page.TableName))
                {
                    while (reader.Read())
                    {
                        string guid = reader["GlobalRecordId"].ToString();

                        if (IdList.ContainsKey(guid))
                        {
                            XmlElement element = IdList[guid];

                            foreach (Field field in page.Fields)
                            {
                                if (field is IDataField && field is RenderableField && !(field is GridField) && !(FieldsToNull.ContainsKey(form.Name) && FieldsToNull[form.Name].Contains(field.Name)))
                                {
                                    RenderableField renderableField = field as RenderableField;
                                    if (renderableField != null)
                                    {
                                        XmlElement fieldData = xmlDataPackage.CreateElement("Field");

                                        XmlAttribute name = xmlDataPackage.CreateAttribute("Name");
                                        name.Value = renderableField.Name;
                                        fieldData.Attributes.Append(name);

                                        string value = reader[field.Name].ToString();

                                        if (!string.IsNullOrEmpty(value))
                                        {
                                            if (field is DateTimeField)
                                            {
                                                DateTime dt = Convert.ToDateTime(value);
                                                fieldData.InnerText = dt.Ticks.ToString();
                                            }
                                            else if (field is ImageField)
                                            {
                                                value = Convert.ToBase64String((Byte[])reader[field.Name]);
                                                fieldData.InnerText = value;
                                            }
                                            else
                                            {
                                                fieldData.InnerText = value;
                                            }
                                        }

                                        if (IncludeNullFieldData == false && String.IsNullOrEmpty(fieldData.InnerText))
                                        {
                                            // do nothing, for now...
                                        }
                                        else
                                        {
                                            element.AppendChild(fieldData);
                                        }
                                        data.AppendChild(element);
                                    }
                                }
                            }
                        }
                        processedRecords++;
                        double progress = (((double)processedRecords) / ((double)totalRecords)) * 100;
                        if (UpdateProgress != null)
                        {
                            UpdateProgress(progress);
                        }
                    }
                }
            }
            foreach (GridField gridField in form.Fields.GridFields)
            {
                data.AppendChild(CreateXmlGridElement(xmlDataPackage, form, gridField));
                ExportInfo.GridsProcessed++;
            }

            return(data);
        }
예제 #2
0
        /// <summary>
        /// Creates an XmlElement representing an Epi Info 7 view's data.
        /// </summary>
        /// <param name="xmlDataPackage">The data package xml document that the XmlElement should be added to</param>
        /// <param name="form">The form whose data will be serialized</param>
        /// <returns>XmlElement; represents the form's data in Xml format, suitable for use in data packaging</returns>
        protected override XmlElement CreateXmlFormDataElement(XmlDocument xmlDataPackage, View form)
        {
            #region Input Validation
            if (xmlDataPackage == null)
            {
                throw new ArgumentNullException("xmlDataPackage");
            }
            if (form == null)
            {
                throw new ArgumentNullException("form");
            }
            #endregion // Input Validation

            XmlElement data = xmlDataPackage.CreateElement("Data");

            OnStatusChanged(String.Format("Packaging data for form {0}...", form.Name));
            OnResetProgress();

            /* This seems like an usual set of steps to just iterate over the data. The problem is that we can't "just
             * iterate over the data" - the data is split up page tables, with one table representing one page on the
             * form. While a JOIN might be able to bring everything together into one table, it might not - for example,
             * if there are >255 fields after the JOIN, an OleDb exception will be thrown.
             *
             * To get around this issue: The code first iterates over the rows in the BASE TABLE, obtaining the GUID
             * values for each. The GUIDs and their corresponding XmlElement go into a dictionary.
             *
             * Later, each row in each page is iterated over; as the GUIDs for each page table are accessed, the corresponding
             * XmlElement is pulled from the dictionary. Field data is added to it for each field that has data. In this
             * manner, it doesn't matter that each row is technically accessed out-of-order because they'll still show up
             * in-order in the resulting Xml.
             *
             * Filtering adds another layer of complexity. To filter, a JOIN operation is needed so that the filters can
             * be applied across all those tables, since the fields in the filter may be across different tables. The
             * RowFilter class provides a way to handle this; we simply get the query from that object and apply it to the
             * reader. Only GUIDs that match the filter are added to the dictionary of guids.
             */

            // We need to exclude records from child forms that may now be orphaned as a result of a filter applied to the parent
            if (form.IsRelatedView && PreviousDistanceFromRoot < CurrentDistanceFromRoot)
            {
                ParentIdList.Clear();
                foreach (KeyValuePair <string, XmlElement> kvp in IdList)
                {
                    ParentIdList.Add(kvp.Key);
                }
            }

            IdList.Clear(); // Very important, this needs to be re-set in case we've already processed a form (this is a class level variable)

            if (!ExportInfo.RecordsPackaged.ContainsKey(form))
            {
                ExportInfo.RecordsPackaged.Add(form, 0);
            }

            //bool filterThisForm = false;
            RowFilters filters     = null;
            Query      selectQuery = null;

            IDbDriver db = SourceProject.CollectedData.GetDatabase();

            string recStatusClause = String.Empty;

            if (Filters != null && Filters.ContainsKey(form.Name) && Filters[form.Name].Count() > 0)
            {
                //filterThisForm = true;
                filters = Filters[form.Name];
                filters.RecordProcessingScope = RecordProcessingScope;
                selectQuery = filters.GetGuidSelectQuery(form);

                List <QueryParameter> paramsToAdd = selectQuery.Parameters;
                selectQuery            = db.CreateQuery(selectQuery.SqlStatement.Replace("[t].[GlobalRecordId], [t].[FKEY], [t].[RECSTATUS]", "*"));
                selectQuery.Parameters = paramsToAdd;
            }
            else
            {
                recStatusClause = "RECSTATUS = 1";

                if (RecordProcessingScope == Epi.RecordProcessingScope.Both)
                {
                    recStatusClause = "RECSTATUS >= 0";
                }
                else if (RecordProcessingScope == Epi.RecordProcessingScope.Deleted)
                {
                    recStatusClause = "RECSTATUS = 0";
                }

                string selectQueryText = "SELECT * " + form.FromViewSQL;

                selectQueryText = "SELECT * " + form.FromViewSQL + " WHERE " + recStatusClause;
                selectQuery     = db.CreateQuery(selectQueryText);
            }

            double totalRecords = Convert.ToDouble(db.ExecuteScalar(db.CreateQuery("SELECT COUNT(*) FROM " + form.TableName)));

            var fieldInclusionList = new List <RenderableField>();

            foreach (Field field in form.Fields)
            {
                if (field is IDataField && field is RenderableField && !(field is GridField) && !(FieldsToNull.ContainsKey(form.Name) && FieldsToNull[form.Name].Contains(field.Name)))
                {
                    var fieldToAdd = field as RenderableField;
                    if (fieldToAdd != null)
                    {
                        fieldInclusionList.Add(fieldToAdd);
                    }
                }
            }

            int processedRecords = 0;

            //using (IDataReader guidReader = db.ExecuteReader(selectQuery))
            //using (IDataReader guidReader = filterThisForm ? db.ExecuteReader(selectQuery) : db.GetTableDataReader(form.TableName))

            DataTable fullTable = db.Select(selectQuery);

            //int lowKey = (int)db.ExecuteScalar(db.CreateQuery("SELECT Min(UniqueKey) FROM " + form.TableName));
            //int highKey = (int)db.ExecuteScalar(db.CreateQuery("SELECT Max(UniqueKey) FROM " + form.TableName));

            ////ProcessRows(fullTable.Select("UniqueKey >= " + lowKey + " AND UniqueKey <= " + (highKey / 4)), form, xmlDataPackage, fieldInclusionList);

            string set1 = String.Empty;
            //string set2 = String.Empty;
            //string set3 = String.Empty;
            //string set4 = String.Empty;

            //Parallel.Invoke(
            //    () =>
            //    {
            set1 = ProcessRows(fullTable.Rows, form, xmlDataPackage, fieldInclusionList);
            //},
            //() =>
            //{
            //    set2 = ProcessRows(fullTable.Select("UniqueKey >= " + (highKey / 4) + " AND UniqueKey < " + (highKey / 2)), form, xmlDataPackage, fieldInclusionList);
            //},
            //() =>
            //{
            //    set3 = ProcessRows(fullTable.Select("UniqueKey >= " + (highKey / 2) + " AND UniqueKey < " + (highKey / 1.5)), form, xmlDataPackage, fieldInclusionList);
            //},
            //() =>
            //{
            //    set4 = ProcessRows(fullTable.Select("UniqueKey >= " + (highKey / 1.5) + " AND UniqueKey <= " + highKey), form, xmlDataPackage, fieldInclusionList);
            //}
            //);

            //StringBuilder sb = new StringBuilder();

            //foreach (XmlElement element in set1)
            //{
            //    sb.Append(element.OuterXml);
            //    //data.AppendChild(element);
            //}

            //foreach (XmlElement element in set2)
            //{
            //    sb.Append(element.OuterXml);
            //    //data.AppendChild(element);
            //}

            //foreach (XmlElement element in set3)
            //{
            //    sb.Append(element.OuterXml);
            //    //data.AppendChild(element);
            //}

            //foreach (XmlElement element in set4)
            //{
            //    sb.Append(element.OuterXml);
            //    //data.AppendChild(element);
            //}

            data.InnerText = set1;

            return(data);


            foreach (DataRow guidReader in fullTable.Rows)
            {
                //using(var conn = new System.Data.SqlClient.SqlConnection(db.ConnectionString + ";Connection Timeout=10"))
                //{
                //    conn.Open();

                //    using (var selectCommand = new System.Data.SqlClient.SqlCommand(selectQueryText, conn))
                //    {
                //        using (var guidReader = selectCommand.ExecuteReader())
                //        {
                //            while (guidReader.Read())
                //            {
                string   guid            = guidReader["GlobalRecordId"].ToString();// guidReader.GetString(0); // guidReader["GlobalRecordId"].ToString();
                string   fkey            = guidReader["FKEY"].ToString();
                string   recstatus       = guidReader["RECSTATUS"].ToString();
                string   firstSaveUserId = String.Empty;
                DateTime?firstSaveTime   = null;
                string   lastSaveUserId  = String.Empty;
                DateTime?lastSaveTime    = null;

                firstSaveUserId = guidReader["FirstSaveLogonName"].ToString();
                if (guidReader["FirstSaveTime"] != DBNull.Value)
                {
                    firstSaveTime = (DateTime)guidReader["FirstSaveTime"];
                }
                lastSaveUserId = guidReader["LastSaveLogonName"].ToString();
                if (guidReader["LastSaveTime"] != DBNull.Value)
                {
                    lastSaveTime = (DateTime)guidReader["LastSaveTime"];
                }

                if (!form.IsRelatedView || ParentIdList.Contains(fkey))
                {
                    XmlElement   record = xmlDataPackage.CreateElement("Record");
                    XmlAttribute id     = xmlDataPackage.CreateAttribute("Id");
                    id.Value = guid;
                    record.Attributes.Append(id);

                    if (!string.IsNullOrEmpty(fkey))
                    {
                        XmlAttribute foreignKey = xmlDataPackage.CreateAttribute("Fkey");
                        foreignKey.Value = fkey;
                        record.Attributes.Append(foreignKey);
                    }
                    if (!string.IsNullOrEmpty(firstSaveUserId))
                    {
                        XmlAttribute firstSaveId = xmlDataPackage.CreateAttribute("FirstSaveUserId");
                        firstSaveId.Value = firstSaveUserId;
                        record.Attributes.Append(firstSaveId);
                    }
                    if (!string.IsNullOrEmpty(lastSaveUserId))
                    {
                        XmlAttribute lastSaveId = xmlDataPackage.CreateAttribute("LastSaveUserId");
                        lastSaveId.Value = lastSaveUserId;
                        record.Attributes.Append(lastSaveId);
                    }
                    if (firstSaveTime.HasValue)
                    {
                        XmlAttribute firstSaveDateTime = xmlDataPackage.CreateAttribute("FirstSaveTime");
                        firstSaveDateTime.Value = firstSaveTime.Value.Ticks.ToString();
                        record.Attributes.Append(firstSaveDateTime);
                    }
                    if (lastSaveTime.HasValue)
                    {
                        XmlAttribute lastSaveDateTime = xmlDataPackage.CreateAttribute("LastSaveTime");
                        lastSaveDateTime.Value = lastSaveTime.Value.Ticks.ToString();
                        record.Attributes.Append(lastSaveDateTime);
                    }
                    if (!String.IsNullOrEmpty(recstatus))
                    {
                        XmlAttribute recStatusAttribute = xmlDataPackage.CreateAttribute("RecStatus");
                        recStatusAttribute.Value = recstatus;
                        record.Attributes.Append(recStatusAttribute);
                    }
                    IdList.Add(guid, record);

                    ExportInfo.TotalRecordsPackaged++;
                    ExportInfo.RecordsPackaged[form]++;

                    foreach (RenderableField field in fieldInclusionList)
                    {
                        XmlElement fieldData = xmlDataPackage.CreateElement("Field");

                        XmlAttribute name = xmlDataPackage.CreateAttribute("Name");
                        name.Value = field.Name;
                        fieldData.Attributes.Append(name);

                        string value = guidReader[field.Name].ToString();

                        if (!String.IsNullOrEmpty(value))
                        {
                            if (field is DateTimeField)
                            {
                                DateTime dt = Convert.ToDateTime(value);
                                fieldData.InnerText = dt.Ticks.ToString();
                            }
                            else if (field is ImageField)
                            {
                                value = Convert.ToBase64String((Byte[])guidReader[field.Name]);
                                fieldData.InnerText = value;
                            }
                            else if (field is NumberField)
                            {
                                value = Convert.ToDouble(value).ToString(System.Globalization.CultureInfo.InvariantCulture);
                                fieldData.InnerText = value;
                            }
                            else
                            {
                                fieldData.InnerText = value;
                            }
                        }

                        if (String.IsNullOrEmpty(fieldData.InnerText) && IncludeNullFieldData == false)
                        {
                            // do nothing, for now...
                        }
                        else
                        {
                            record.AppendChild(fieldData);
                        }
                        data.AppendChild(record);
                    }
                }

                processedRecords++;
                double progress = (((double)processedRecords) / ((double)totalRecords)) * 100;
                OnProgressChanged(progress);
            }

            foreach (GridField gridField in form.Fields.GridFields)
            {
                data.AppendChild(CreateXmlGridElement(xmlDataPackage, form, gridField));
                ExportInfo.GridsProcessed++;
            }

            return(data);
        }