コード例 #1
0
ファイル: DataReader.cs プロジェクト: arnovb-github/CmcLibNet
        /// <summary>
        /// Reads data using DDE. This is extremely show and should only ever be used as a last resort.
        /// </summary>
        /// <param name="mocktables"></param>
        internal void GetDataByDDE(List <TableDef> mocktables) // needs fixing
        {
            /* DDE requests are limited to a maximum length of 255 characters,
             * which is easily exceeded. A workaround is splitting the requests.
             * Not pretty but the only way to get to many-many relationships that contain >93750 worth of connected characters
             * without setting the maxfieldsize higher.
             */

            List <List <CommenceValue> > rows;
            List <CommenceValue>         rowvalues;
            ICommenceDatabase            db = new CommenceDatabase();

            // always define a category
            db.ViewCategory(this.cursor.Category);
            // are we dealing with a view?
            if (!string.IsNullOrEmpty(cursor.View))
            {
                db.ViewView(this.cursor.View);
            }
            int itemCount = db.ViewItemCount();

            for (int i = 1; i <= itemCount; i++) // note that we use a 1-based iterator
            {
                rows      = new List <List <CommenceValue> >();
                rowvalues = new List <CommenceValue>();
                foreach (TableDef td in mocktables)
                {
                    string[]      DDEResult  = null;
                    List <string> fieldNames = td.ColumnDefinitions.Select(o => o.FieldName).ToList();
                    if (td.Primary)
                    {
                        // ViewFields and ViewConnectedFields have a limited capacity
                        // the total length of a DDE command cannot exceed 255 characters
                        // What we are going to do is limit the number of characters to a value of up to 150 chars,
                        // to be on the safe side (ViewConnectedFilter and two delimiters already make up 35 characters!)
                        ListChopper lcu = new ListChopper(fieldNames, 150);
                        foreach (List <string> l in lcu.Portions)
                        {
                            DDEResult = db.ViewFields(i, l);

                            // we have our results, we now have to create CommenceValue objects from it
                            // and we also have to match them up with their respective column
                            // this is a little tricky...
                            for (int j = 0; j < DDEResult.Length; j++)
                            {
                                ColumnDefinition cd     = td.ColumnDefinitions.Find(o => o.FieldName.Equals(l[j]));
                                string[]         buffer = new string[] { DDEResult[j] };
                                //buffer = FormatValues(buffer,this.Formatting, cd);
                                buffer = FormatValues(buffer, cd);
                                CommenceValue v = new CommenceValue(buffer[0], cd);
                                rowvalues.Add(v);
                            } // for
                        }     // list l
                    }
                    else      // we are dealing with a connection
                    {
                        int conItemCount = db.ViewConnectedCount(i, td.ColumnDefinitions[0].Connection, td.ColumnDefinitions[0].Category); // doesn't matter which one we use
                        // here's a nice challenge:
                        // upon every iteration we get a row of fieldvalues from the connection
                        // to make things worse, we chop them up so it aren't even complete rows.
                        // we must aggregate the values for each field.
                        // We'll construct a datatable to hack around that;
                        // we could have also used a dictionary I suppose.

                        //  using a datatable may be easiest
                        DataTable dt = new DataTable();
                        for (int c = 0; c < fieldNames.Count; c++)
                        {
                            dt.Columns.Add(fieldNames[c]); // add fields as columns, keeping everything default
                        }

                        // loop all connected items
                        for (int citemcount = 1; citemcount <= conItemCount; citemcount++)
                        {
                            DataRow     dr  = dt.NewRow(); // create a row containing all columns
                            ListChopper lcu = new ListChopper(fieldNames, 150);
                            foreach (List <string> list in lcu.Portions)
                            {
                                DDEResult = db.ViewConnectedFields(i, td.ColumnDefinitions[0].Connection, td.ColumnDefinitions[0].Category, citemcount, list);
                                // populate colums for the fields we requested
                                for (int j = 0; j < DDEResult.Length; j++)
                                {
                                    dr[list[j]] = DDEResult[j];
                                }
                            } // list l
                            dt.Rows.Add(dr);
                        }     // citemcount

                        // create a CommenceValue from every column in the datatable
                        foreach (DataColumn dc in dt.Columns)
                        {
                            // this will also return columns that have no data, which is what we want.
                            string[] query =
                                (from r in dt.AsEnumerable()
                                 select r.Field <String>(dc.ColumnName)).ToArray();
                            ColumnDefinition cd = td.ColumnDefinitions.Find(o => o.FieldName.Equals(dc.ColumnName));
                            CommenceValue    cv = null;
                            if (query.Length > 0) // only create value if there is one
                            {
                                //query = FormatValues(query, this.Formatting, cd);
                                query = FormatValues(query, cd);
                                cv    = new CommenceValue(query, cd);
                            }
                            else
                            {
                                // create empty CommenceValue
                                cv = new CommenceValue(cd);
                            }
                            rowvalues.Add(cv);
                        }
                    } // if
                }     // foreach tabledef
                rows.Add(rowvalues);
                CursorDataReadProgressChangedArgs args = new CursorDataReadProgressChangedArgs(rows, i, totalRows); // progress within the cursor
                OnDataProgressChanged(args);
            } // i
            db = null;
            ExportCompleteArgs a = new ExportCompleteArgs(itemCount);

            OnDataReadCompleted(a);
        }
コード例 #2
0
        protected override void ProcessRecord()
        {
            var    db     = new CommenceDatabase();
            string result = db.ViewCategory(fromCategory); // if fromCategory is not found, nothing happens

            if (result.ToLower() != "ok")
            {
                WriteError(new ErrorRecord(new Vovin.CmcLibNet.CommenceDDEException(result),
                                           "CategoryNotFound",
                                           ErrorCategory.InvalidResult,
                                           db));
                return;
            }
            string clarifyState = db.ClarifyItemNames();

            try {
                int connectedItemCount = -1;
                // no item supplied, process entire category
                if (string.IsNullOrEmpty(fromItem))
                {
                    int           numItems  = db.GetItemCount(fromCategory);
                    List <string> itemNames = db.GetItemNames(fromCategory);
                    db.ClarifyItemNames("TRUE");
                    for (int i = 1; i <= numItems; i++) // DDE-call indexes in Commence are 1-based
                    {
                        // since this not rely on string values, it should be reliable
                        connectedItemCount = db.ViewConnectedCount(i, connectionName, toCategory);
                        WriteObject(new
                        {
                            ItemName     = itemNames[i - 1],
                            FromCategory = fromCategory,
                            Connection   = connectionName,
                            ToCategory   = toCategory,
                            Count        = connectedItemCount
                        },
                                    false); // return and do not enumerate. I.e. pass every object separately.
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(clarifyValue) && !string.IsNullOrEmpty(clarifySeparator))
                    {
                        fromItem = db.GetClarifiedItemName(fromItem, clarifySeparator, clarifyValue);
                        db.ClarifyItemNames("TRUE");
                    }
                    connectedItemCount = db.GetConnectedItemCount(fromCategory, fromItem, connectionName, toCategory);
                    WriteObject(new
                    {
                        ItemName     = fromItem,
                        FromCategory = fromCategory,
                        Connection   = connectionName,
                        ToCategory   = toCategory,
                        Count        = connectedItemCount
                    },
                                false);
                }
                if (connectedItemCount == -1)
                {
                    WriteError(new ErrorRecord(new Vovin.CmcLibNet.CommenceDDEException("Vovin.CmcLibNet was unable to get a valid result from Commence."),
                                               "CommenceDDEError",
                                               ErrorCategory.InvalidArgument,
                                               db));

                    WriteVerbose("A count of -1 means an error occurred while trying to receive the count from Commence.\n"
                                 + "This is likely caused by one or more of the arguments being invalid.\n"
                                 + "Note that connection- and viewnames in Commence are case-sensitive!\n\n"
                                 + "A clarify separator may include spaces. Make sure to include them in the command.\n\n");
                    return;
                }
            }
            finally
            {
                db.ClarifyItemNames(clarifyState); // restore state
                db.Close();
            }
        }