public static ulong?RetrieveColumnAsUInt64(
     JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
 {
     unsafe
     {
         const int DataSize = sizeof(ulong);
         ulong     data;
         var       pointer = new IntPtr(&data);
         int       actualDataSize;
         JET_wrn   wrn = JetRetrieveColumn(
             sesid, tableid, columnid, pointer, DataSize, out actualDataSize, grbit, null);
         return(CreateReturnValue(data, DataSize, wrn, actualDataSize));
     }
 }
Exemplo n.º 2
0
 /// <summary>
 /// Sets the fields of the object from a native JET_INDEXLIST struct.
 /// </summary>
 /// <param name="value">
 /// The native indexlist to set the values from.
 /// </param>
 internal void SetFromNativeIndexlist(NATIVE_INDEXLIST value)
 {
     this.tableid = new JET_TABLEID {
         Value = value.tableid
     };
     this.cRecord           = checked ((int)value.cRecord);
     this.columnidindexname = new JET_COLUMNID {
         Value = value.columnidindexname
     };
     this.columnidgrbitIndex = new JET_COLUMNID {
         Value = value.columnidgrbitIndex
     };
     this.columnidcKey = new JET_COLUMNID {
         Value = value.columnidcKey
     };
     this.columnidcEntry = new JET_COLUMNID {
         Value = value.columnidcEntry
     };
     this.columnidcPage = new JET_COLUMNID {
         Value = value.columnidcPage
     };
     this.columnidcColumn = new JET_COLUMNID {
         Value = value.columnidcColumn
     };
     this.columnidiColumn = new JET_COLUMNID {
         Value = value.columnidiColumn
     };
     this.columnidcolumnid = new JET_COLUMNID {
         Value = value.columnidcolumnid
     };
     this.columnidcoltyp = new JET_COLUMNID {
         Value = value.columnidcoltyp
     };
     this.columnidLangid = new JET_COLUMNID {
         Value = value.columnidLangid
     };
     this.columnidCp = new JET_COLUMNID {
         Value = value.columnidCp
     };
     this.columnidgrbitColumn = new JET_COLUMNID {
         Value = value.columnidgrbitColumn
     };
     this.columnidcolumnname = new JET_COLUMNID {
         Value = value.columnidcolumnname
     };
     this.columnidLCMapFlags = new JET_COLUMNID {
         Value = value.columnidLCMapFlags
     };
 }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a dictionary which maps column names to their column IDs.
        /// </summary>
        /// <param name="sesid">The sesid to use.</param>
        /// <param name="tableid">The table to retrieve the information for.</param>
        /// <returns>A dictionary mapping column names to column IDs.</returns>
        public static IDictionary <string, JET_COLUMNID> GetColumnDictionary(JET_SESID sesid, JET_TABLEID tableid)
        {
            JET_COLUMNLIST columnlist;

            JetGetTableColumnInfo(sesid, tableid, string.Empty, out columnlist);

            // As of Sep 2015, JetGetColumnInfoW is only called for Win8+. Even though Unicode should have
            // worked in Win7, it wasn't reliable until Win8.
            Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features ? Encoding.Unicode : LibraryHelpers.EncodingASCII;

            try
            {
                // esent treats column names as case-insensitive, so we want the dictionary to be case insensitive as well
                var dict = new Dictionary <string, JET_COLUMNID>(
                    columnlist.cRecord, StringComparer.OrdinalIgnoreCase);
                if (columnlist.cRecord > 0)
                {
                    if (Api.TryMoveFirst(sesid, columnlist.tableid))
                    {
                        do
                        {
                            string name = RetrieveColumnAsString(
                                sesid,
                                columnlist.tableid,
                                columnlist.columnidcolumnname,
                                encodingOfTextColumns,
                                RetrieveColumnGrbit.None);
                            name = StringCache.TryToIntern(name);
                            var columnidValue =
                                (uint)RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid);

                            var columnid = new JET_COLUMNID {
                                Value = columnidValue
                            };
                            dict.Add(name, columnid);
                        }while (TryMoveNext(sesid, columnlist.tableid));
                    }
                }

                return(dict);
            }
            finally
            {
                // Close the temporary table used to return the results
                JetCloseTable(sesid, columnlist.tableid);
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Initializes a new instance of the ColumnInfo class.
 /// </summary>
 /// <param name="name">Name of the column.</param>
 /// <param name="columnid">ID of the column.</param>
 /// <param name="coltyp">Type of the column.</param>
 /// <param name="cp">Codepage of the column.</param>
 /// <param name="maxLength">Maximum length of the column.</param>
 /// <param name="defaultValue">Column default value.</param>
 /// <param name="grbit">Column option.</param>
 internal ColumnInfo(
     string name,
     JET_COLUMNID columnid,
     JET_coltyp coltyp,
     JET_CP cp,
     int maxLength,
     byte[] defaultValue,
     ColumndefGrbit grbit)
 {
     this.Name = name;
     this.Columnid = columnid;
     this.Coltyp = coltyp;
     this.Cp = cp;
     this.MaxLength = maxLength;
     this.defaultValue = (null == defaultValue) ? null : Array.AsReadOnly(defaultValue);
     this.Grbit = grbit;
 }
        /// <summary>
        /// Retrieves the size of a single column value from the current record.
        /// The record is that record associated with the index entry at the
        /// current position of the cursor. Alternatively, this function can
        /// retrieve a column from a record being created in the cursor copy
        /// buffer. This function can also retrieve column data from an index
        /// entry that references the current record.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="itagSequence">
        /// The sequence number of value in a multi-valued column.
        /// The array of values is one-based. The first value is
        /// sequence 1, not 0. If the record column has only one value then
        /// 1 should be passed as the itagSequence.
        /// </param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <returns>The size of the column. 0 if the column is null.</returns>
        public static int?RetrieveColumnSize(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, int itagSequence, RetrieveColumnGrbit grbit)
        {
            var retinfo = new JET_RETINFO {
                itagSequence = itagSequence
            };
            int     dataSize;
            JET_wrn wrn = JetRetrieveColumn(
                sesid, tableid, columnid, null, 0, out dataSize, grbit, retinfo);

            if (JET_wrn.ColumnNull == wrn)
            {
                return(null);
            }

            return(dataSize);
        }
        /// <summary>
        /// Retrieves a single column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// Alternatively, this function can retrieve a column from a record being created
        /// in the cursor copy buffer. This function can also retrieve column data from an
        /// index entry that references the current record. In addition to retrieving the
        /// actual column value, JetRetrieveColumn can also be used to retrieve the size
        /// of a column, before retrieving the column data itself so that application
        /// buffers can be sized appropriately.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <param name="retinfo">
        /// If pretinfo is give as NULL then the function behaves as though an itagSequence
        /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
        /// retrieve the first value of a multi-valued column, and to retrieve long data at
        /// offset 0 (zero).
        /// </param>
        /// <returns>The data retrieved from the column. Null if the column is null.</returns>
        public static byte[] RetrieveColumn(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
        {
            // We expect most column values retrieved this way to be small (retrieving a 1GB LV as one
            // chunk is a bit extreme!). Allocate a cached buffer and use that, allocating a larger one
            // if needed.
            byte[]  cache = Caches.ColumnCache.Allocate();
            byte[]  data  = cache;
            int     dataSize;
            JET_wrn wrn = JetRetrieveColumn(
                sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo);

            if (JET_wrn.ColumnNull == wrn)
            {
                // null column
                data = null;
            }
            else if (JET_wrn.Success == wrn)
            {
                data = MemoryCache.Duplicate(data, dataSize);
            }
            else
            {
                // there is more data to retrieve
                Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning", wrn.ToString());
                data = new byte[dataSize];
                wrn  = JetRetrieveColumn(
                    sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo);
                if (JET_wrn.Success != wrn)
                {
                    string error = String.Format(
                        CultureInfo.CurrentCulture,
                        "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                        data.Length,
                        dataSize);
                    Trace.TraceError(error);
                    throw new InvalidOperationException(error);
                }
            }

            Caches.ColumnCache.Free(ref cache);
            return(data);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Creates a dictionary which maps column names to their column IDs.
        /// </summary>
        /// <param name="sesid">The sesid to use.</param>
        /// <param name="tableid">The table to retrieve the information for.</param>
        /// <returns>A dictionary mapping column names to column IDs.</returns>
        public static IDictionary <string, JET_COLUMNID> GetColumnDictionary(JET_SESID sesid, JET_TABLEID tableid)
        {
            JET_COLUMNLIST columnlist;

            JetGetTableColumnInfo(sesid, tableid, string.Empty, out columnlist);
            try
            {
                // esent treats column names as case-insensitive, so we want the dictionary to be case insensitive as well
                var dict = new Dictionary <string, JET_COLUMNID>(
                    columnlist.cRecord, StringComparer.OrdinalIgnoreCase);
                if (columnlist.cRecord > 0)
                {
                    if (Api.TryMoveFirst(sesid, columnlist.tableid))
                    {
                        do
                        {
                            string name = RetrieveColumnAsString(
                                sesid,
                                columnlist.tableid,
                                columnlist.columnidcolumnname,
                                NativeMethods.Encoding,
                                RetrieveColumnGrbit.None);
                            name = StringCache.TryToIntern(name);
                            var columnidValue =
                                (uint)RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid);

                            var columnid = new JET_COLUMNID {
                                Value = columnidValue
                            };
                            dict.Add(name, columnid);
                        }while (TryMoveNext(sesid, columnlist.tableid));
                    }
                }

                return(dict);
            }
            finally
            {
                // Close the temporary table used to return the results
                JetCloseTable(sesid, columnlist.tableid);
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Perform atomic addition on one column. The column must be of type
        /// <see cref="JET_coltyp.Long"/>. This function allows multiple sessions to update the
        /// same record concurrently without conflicts.
        /// </summary>
        /// <remarks>
        /// This method wraps <see cref="JetEscrowUpdate"/>.
        /// </remarks>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to update.</param>
        /// <param name="columnid">The column to update. This must be an escrow-updatable column.</param>
        /// <param name="delta">The delta to apply to the column.</param>
        /// <returns>The current value of the column as stored in the database (versioning is ignored).</returns>
        public static int EscrowUpdate(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, int delta)
        {
            var previousValue = new byte[sizeof(int)];
            int actualPreviousValueLength;

            JetEscrowUpdate(
                sesid,
                tableid,
                columnid,
                BitConverter.GetBytes(delta),
                sizeof(int),
                previousValue,
                previousValue.Length,
                out actualPreviousValueLength,
                EscrowUpdateGrbit.None);
            Debug.Assert(
                previousValue.Length == actualPreviousValueLength,
                "Unexpected previous value length. Expected an Int32");
            return(BitConverter.ToInt32(previousValue, 0));
        }
        /// <summary>
        /// Retrieves a single column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// Alternatively, this function can retrieve a column from a record being created
        /// in the cursor copy buffer. This function can also retrieve column data from an
        /// index entry that references the current record. In addition to retrieving the
        /// actual column value, JetRetrieveColumn can also be used to retrieve the size
        /// of a column, before retrieving the column data itself so that application
        /// buffers can be sized appropriately.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <param name="retinfo">
        /// If pretinfo is give as NULL then the function behaves as though an itagSequence
        /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
        /// retrieve the first value of a multi-valued column, and to retrieve long data at
        /// offset 0 (zero).
        /// </param>
        /// <returns>The data retrieved from the column. Null if the column is null.</returns>
        public static byte[] RetrieveColumn(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
        {
            // We expect most column values retrieved this way to be small (retrieving a 1GB LV as one
            // chunk is a bit extreme!). Allocate a small buffer and use that, allocating a larger one
            // if needed.
            var     data = new byte[256];
            int     dataSize;
            JET_wrn wrn = JetRetrieveColumn(
                sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo);

            if (JET_wrn.ColumnNull == wrn)
            {
                // null column
                data = null;
            }
            else
            {
                Array.Resize(ref data, dataSize);
                if (JET_wrn.BufferTruncated == wrn)
                {
                    // there is more data to retrieve
                    wrn = JetRetrieveColumn(
                        sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo);
                    if (JET_wrn.Success != wrn)
                    {
                        string error = String.Format(
                            CultureInfo.CurrentCulture,
                            "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                            data.Length,
                            dataSize);
                        Trace.TraceError(error);
                        throw new InvalidOperationException(error);
                    }
                }
            }

            return(data);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Modifies a single column value in a modified record to be inserted or to
        /// update the current record.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to update. An update should be prepared.</param>
        /// <param name="columnid">The columnid to set.</param>
        /// <param name="data">The data to set.</param>
        /// <param name="encoding">The encoding used to convert the string.</param>
        /// <param name="grbit">SetColumn options.</param>
        public static void SetColumn(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, string data, Encoding encoding, SetColumnGrbit grbit)
        {
            CheckEncodingIsValid(encoding);

            if (null == data)
            {
                JetSetColumn(sesid, tableid, columnid, null, 0, grbit, null);
            }
            else if (0 == data.Length)
            {
                JetSetColumn(sesid, tableid, columnid, null, 0, grbit | SetColumnGrbit.ZeroLength, null);
            }
            else if (Encoding.Unicode == encoding)
            {
                // Optimization for setting Unicode strings.
                unsafe
                {
                    fixed(char *buffer = data)
                    {
                        JetSetColumn(
                            sesid,
                            tableid,
                            columnid,
                            new IntPtr(buffer),
                            checked (data.Length * sizeof(char)),
                            grbit,
                            null);
                    }
                }
            }
            else
            {
                byte[] bytes = encoding.GetBytes(data);
                JetSetColumn(sesid, tableid, columnid, bytes, bytes.Length, grbit, null);
            }
        }
Exemplo n.º 11
0
 /// <summary>
 /// Modifies a single column value in a modified record to be inserted or to
 /// update the current record.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to update. An update should be prepared.</param>
 /// <param name="columnid">The columnid to set.</param>
 /// <param name="data">The data to set.</param>
 public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, DateTime data)
 {
     SetColumn(sesid, tableid, columnid, data.ToOADate());
 }
Exemplo n.º 12
0
        /// <summary>
        /// Retrieves a string column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="encoding">The string encoding to use when converting data.</param>
        /// <param name="grbit">Retrieval options.</param>
        /// <returns>The data retrieved from the column as a string. Null if the column is null.</returns>
        public static string RetrieveColumnAsString(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, Encoding encoding, RetrieveColumnGrbit grbit)
        {
            JET_wrn wrn;

            // This is an optimization for retrieving small Unicode strings
            // We use a stack-allocated buffer to retrieve the data and then create
            // a string from the data
            if (Encoding.Unicode == encoding)
            {
                unsafe
                {
                    // 512 bytes give 256 Unicode characters.
                    const int BufferSize = 512;
                    char *    buffer     = stackalloc char[BufferSize];
                    int       actualDataSize;
                    wrn = JetRetrieveColumn(
                        sesid, tableid, columnid, new IntPtr(buffer), BufferSize, out actualDataSize, grbit, null);
                    if (JET_wrn.ColumnNull == wrn)
                    {
                        return(null);
                    }

                    if (JET_wrn.Success == wrn)
                    {
                        return(new string(buffer, 0, actualDataSize / sizeof(char)));
                    }

                    Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning code");

                    // Fallthrough to normal case below
                }
            }

            // Retrieving a string happens in two stages: first the data is retrieved into a data
            // buffer and then the buffer is converted to a string. The buffer isn't needed for
            // very long so we try to use a cached buffer.
            byte[] cachedBuffer = memoryCache.Allocate();
            byte[] data         = cachedBuffer;

            int dataSize;

            wrn = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null);
            if (JET_wrn.ColumnNull == wrn)
            {
                return(null);
            }

            if (JET_wrn.BufferTruncated == wrn)
            {
                Debug.Assert(dataSize > data.Length, "Expected column to be bigger than buffer");
                data = new byte[dataSize];
                wrn  = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null);
                if (JET_wrn.BufferTruncated == wrn)
                {
                    string error = String.Format(
                        CultureInfo.CurrentCulture,
                        "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                        data.Length,
                        dataSize);
                    Trace.TraceError(error);
                    throw new InvalidOperationException(error);
                }
            }

            // TODO: for Unicode strings pin the buffer and use the String(char*) constructor.
            string s = encoding.GetString(data, 0, dataSize);

            // Now we have extracted the string from the buffer we can free (cache) the buffer.
            memoryCache.Free(cachedBuffer);

            return(s);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Modifies a single column value in a modified record to be inserted or to
        /// update the current record.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to update. An update should be prepared.</param>
        /// <param name="columnid">The columnid to set.</param>
        /// <param name="data">The data to set.</param>
        public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, bool data)
        {
            byte b = data ? (byte)0xff : (byte)0x0;

            SetColumn(sesid, tableid, columnid, b);
        }
Exemplo n.º 14
0
 /// <summary>
 /// Retrieves a string column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <param name="encoding">The string encoding to use when converting data.</param>
 /// <returns>The data retrieved from the column as a string. Null if the column is null.</returns>
 public static string RetrieveColumnAsString(
     JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, Encoding encoding)
 {
     return(RetrieveColumnAsString(sesid, tableid, columnid, encoding, RetrieveColumnGrbit.None));
 }
Exemplo n.º 15
0
 /// <summary>
 /// Retrieves a single column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <returns>The data retrieved from the column. Null if the column is null.</returns>
 public static byte[] RetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid)
 {
     return(RetrieveColumn(sesid, tableid, columnid, RetrieveColumnGrbit.None, null));
 }
Exemplo n.º 16
0
 /// <summary>
 /// Write a serialized form of an object to a column.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The table to write to. An update should be prepared.</param>
 /// <param name="columnid">The column to write to.</param>
 /// <param name="value">The object to write. The object must be serializable.</param>
 public static void SerializeObjectToColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, object value)
 {
     if (null == value)
     {
         Api.SetColumn(sesid, tableid, columnid, null);
     }
     else
     {
         using (var stream = new ColumnStream(sesid, tableid, columnid))
         {
             var serializer = new BinaryFormatter
             {
                 Context = new StreamingContext(StreamingContextStates.Persistence)
             };
             serializer.Serialize(stream, value);
         }
     }
 }
Exemplo n.º 17
0
 /// <summary>
 /// Retrieves a guid column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <returns>The data retrieved from the column as a guid. Null if the column is null.</returns>
 public static Guid?RetrieveColumnAsGuid(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid)
 {
     return(RetrieveColumnAsGuid(sesid, tableid, columnid, RetrieveColumnGrbit.None));
 }
Exemplo n.º 18
0
        /// <summary>
        /// Retrieve a Unicode (UTF16) string. This is optimized to take advantage of the fact
        /// that no conversion is needed.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The table to retrieve from.</param>
        /// <param name="columnid">The column to retrieve.</param>
        /// <param name="grbit">Retrieve options.</param>
        /// <returns>The string retrieved from the column.</returns>
        private static unsafe string RetrieveUnicodeString(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
        {
            // 512 Unicode characters (1kb on stack)
            const int BufferSize = 512;
            char *    buffer     = stackalloc char[BufferSize];
            int       actualDataSize;
            JET_wrn   wrn = JetRetrieveColumn(sesid, tableid, columnid, new IntPtr(buffer), BufferSize * sizeof(char), out actualDataSize, grbit, null);

            if (JET_wrn.ColumnNull == wrn)
            {
                return(null);
            }

            if (JET_wrn.Success == wrn)
            {
                ////return StringCache.GetString(buffer, 0, actualDataSize);
                return(new string(buffer, 0, actualDataSize / sizeof(char)));
            }

            Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning code");

            // Create a fake string of the appropriate size and then fill it in.
            var s = new string('\0', actualDataSize / sizeof(char));

            fixed(char *p = s)
            {
                int newDataSize;

                wrn = JetRetrieveColumn(sesid, tableid, columnid, new IntPtr(p), actualDataSize, out newDataSize, grbit, null);
                if (JET_wrn.BufferTruncated == wrn)
                {
                    string error = String.Format(
                        CultureInfo.CurrentCulture,
                        "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                        actualDataSize,
                        newDataSize);
                    Trace.TraceError(error);
                    throw new InvalidOperationException(error);
                }
            }

            return(s);
        }
Exemplo n.º 19
0
 /// <summary>
 /// Retrieves a single column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// Alternatively, this function can retrieve a column from a record being created
 /// in the cursor copy buffer. This function can also retrieve column data from an
 /// index entry that references the current record. In addition to retrieving the
 /// actual column value, JetRetrieveColumn can also be used to retrieve the size
 /// of a column, before retrieving the column data itself so that application
 /// buffers can be sized appropriately.
 /// </summary>
 /// <remarks>
 /// This is an internal-use version that takes an IntPtr.
 /// </remarks>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <param name="data">The data buffer to be retrieved into.</param>
 /// <param name="dataSize">The size of the data buffer.</param>
 /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
 /// <param name="grbit">Retrieve column options.</param>
 /// <param name="retinfo">
 /// If pretinfo is give as NULL then the function behaves as though an itagSequence
 /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
 /// retrieve the first value of a multi-valued column, and to retrieve long data at
 /// offset 0 (zero).
 /// </param>
 /// <returns>An ESENT warning code.</returns>
 internal static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
 {
     return(Api.Check(Impl.JetRetrieveColumn(sesid, tableid, columnid, data, dataSize, out actualDataSize, grbit, retinfo)));
 }
Exemplo n.º 20
0
        /// <summary>
        /// Modifies a single column value in a modified record to be inserted or to
        /// update the current record.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to update. An update should be prepared.</param>
        /// <param name="columnid">The columnid to set.</param>
        /// <param name="data">The data to set.</param>
        /// <param name="encoding">The encoding used to convert the string.</param>
        /// <param name="grbit">SetColumn options.</param>
        public static void SetColumn(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, string data, Encoding encoding, SetColumnGrbit grbit)
        {
            CheckEncodingIsValid(encoding);

            if (null == data)
            {
                JetSetColumn(sesid, tableid, columnid, null, 0, grbit, null);
            }
            else if (0 == data.Length)
            {
                JetSetColumn(sesid, tableid, columnid, null, 0, grbit | SetColumnGrbit.ZeroLength, null);
            }
            else if (Encoding.Unicode == encoding)
            {
                // Optimization for setting Unicode strings.
                unsafe
                {
                    fixed(char *buffer = data)
                    {
                        JetSetColumn(
                            sesid,
                            tableid,
                            columnid,
                            new IntPtr(buffer),
                            checked (data.Length * sizeof(char)),
                            grbit,
                            null);
                    }
                }
            }
            else if (encoding.GetMaxByteCount(data.Length) <= Caches.ColumnCache.BufferSize)
            {
#if MANAGEDESENT_ON_WSA
                // Encoding.GetBytes(char*, int, byte*, int) overload is missing in new Windows UI.
                // So we can't use the ColumnCache. We'll just use a different GetBytes() overload.
                byte[] buffer = encoding.GetBytes(data);
                unsafe
                {
                    fixed(byte *bytes = buffer)
                    {
                        JetSetColumn(sesid, tableid, columnid, new IntPtr(bytes), buffer.Length, grbit, null);
                    }
                }
#else
                // The encoding output will fix in a cached buffer. Get one to avoid
                // more memory allocations.
                byte[] buffer = null;

                try
                {
                    buffer = Caches.ColumnCache.Allocate();
                    unsafe
                    {
                        fixed(char *chars = data)
                        fixed(byte *bytes = buffer)
                        {
                            int dataSize = encoding.GetBytes(chars, data.Length, bytes, buffer.Length);

                            JetSetColumn(sesid, tableid, columnid, new IntPtr(bytes), dataSize, grbit, null);
                        }
                    }
                }
                finally
                {
                    if (buffer != null)
                    {
                        Caches.ColumnCache.Free(ref buffer);
                    }
                }
#endif
            }
            else
            {
                byte[] bytes = encoding.GetBytes(data);
                JetSetColumn(sesid, tableid, columnid, bytes, bytes.Length, grbit, null);
            }
        }
Exemplo n.º 21
0
 /// <summary>
 /// Retrieves the size of a single column value from the current record.
 /// The record is that record associated with the index entry at the
 /// current position of the cursor. Alternatively, this function can
 /// retrieve a column from a record being created in the cursor copy
 /// buffer. This function can also retrieve column data from an index
 /// entry that references the current record.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <returns>The size of the column. 0 if the column is null.</returns>
 public static int?RetrieveColumnSize(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid)
 {
     return(RetrieveColumnSize(sesid, tableid, columnid, 1, RetrieveColumnGrbit.None));
 }
Exemplo n.º 22
0
 /// <summary>
 /// Deserialize an object from a column.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The table to read from.</param>
 /// <param name="columnid">The column to read from.</param>
 /// <returns>The deserialized object. Null if the column was null.</returns>
 public static object DeserializeObjectFromColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid)
 {
     return(DeserializeObjectFromColumn(sesid, tableid, columnid, RetrieveColumnGrbit.None));
 }
Exemplo n.º 23
0
 public static ulong?RetrieveColumnAsUInt64(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid)
 {
     return(RetrieveColumnAsUInt64(sesid, tableid, columnid, RetrieveColumnGrbit.None));
 }
Exemplo n.º 24
0
 /// <summary>
 /// Retrieves a datetime column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <returns>The data retrieved from the column as a datetime. Null if the column is null.</returns>
 public static DateTime?RetrieveColumnAsDateTime(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid)
 {
     return(RetrieveColumnAsDateTime(sesid, tableid, columnid, RetrieveColumnGrbit.None));
 }
Exemplo n.º 25
0
 /// <summary>
 /// Modifies a single column value in a modified record to be inserted or to
 /// update the current record.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to update. An update should be prepared.</param>
 /// <param name="columnid">The columnid to set.</param>
 /// <param name="data">The data to set.</param>
 public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data)
 {
     SetColumn(sesid, tableid, columnid, data, SetColumnGrbit.None);
 }
Exemplo n.º 26
0
 /// <summary>
 /// The JetSetColumn function modifies a single column value in a modified record to be inserted or to
 /// update the current record. It can overwrite an existing value, add a new value to a sequence of
 /// values in a multi-valued column, remove a value from a sequence of values in a multi-valued column,
 /// or update all or part of a long value, a column of type JET_coltyp.LongText or JET_coltyp.LongBinary.
 /// </summary>
 /// <remarks>
 /// This method takes an IntPtr and is intended for internal use only.
 /// </remarks>
 /// <param name="sesid">The session which is performing the update.</param>
 /// <param name="tableid">The cursor to update. An update should be prepared.</param>
 /// <param name="columnid">The columnid to set.</param>
 /// <param name="data">The data to set.</param>
 /// <param name="dataSize">The size of data to set.</param>
 /// <param name="grbit">SetColumn options.</param>
 /// <param name="setinfo">Used to specify itag or long-value offset.</param>
 /// <returns>A warning value.</returns>
 internal static JET_wrn JetSetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, SetColumnGrbit grbit, JET_SETINFO setinfo)
 {
     return(Api.Check(Impl.JetSetColumn(sesid, tableid, columnid, data, dataSize, grbit, setinfo)));
 }
Exemplo n.º 27
0
 /// <summary>
 /// Modifies a single column value in a modified record to be inserted or to
 /// update the current record.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to update. An update should be prepared.</param>
 /// <param name="columnid">The columnid to set.</param>
 /// <param name="data">The data to set.</param>
 /// <param name="encoding">The encoding used to convert the string.</param>
 public static void SetColumn(
     JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, string data, Encoding encoding)
 {
     SetColumn(sesid, tableid, columnid, data, encoding, SetColumnGrbit.None);
 }
Exemplo n.º 28
0
        /// <summary>
        /// Retrieves a single column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// Alternatively, this function can retrieve a column from a record being created
        /// in the cursor copy buffer. This function can also retrieve column data from an
        /// index entry that references the current record. In addition to retrieving the
        /// actual column value, JetRetrieveColumn can also be used to retrieve the size
        /// of a column, before retrieving the column data itself so that application
        /// buffers can be sized appropriately.
        /// </summary>
        /// <remarks>
        /// This is an internal method that takes a buffer offset as well as size.
        /// </remarks>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="data">The data buffer to be retrieved into.</param>
        /// <param name="dataSize">The size of the data buffer.</param>
        /// <param name="dataOffset">Offset into the data buffer to read data into.</param>
        /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <param name="retinfo">
        /// If pretinfo is give as NULL then the function behaves as though an itagSequence
        /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
        /// retrieve the first value of a multi-valued column, and to retrieve long data at
        /// offset 0 (zero).
        /// </param>
        /// <returns>An ESENT warning code.</returns>
        public static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, int dataOffset, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
        {
            if (dataOffset < 0 ||
                (null != data && 0 != dataSize && dataOffset >= data.Length) ||
                (null == data && dataOffset != 0))
            {
                throw new ArgumentOutOfRangeException(
                          "dataOffset",
                          dataOffset,
                          "must be inside the data buffer");
            }

            if ((null == data && dataSize > 0) || (null != data && dataSize > data.Length))
            {
                throw new ArgumentOutOfRangeException(
                          "dataSize",
                          dataSize,
                          "cannot be greater than the length of the data");
            }

            unsafe
            {
                fixed(byte *pointer = data)
                {
                    return(Api.JetRetrieveColumn(
                               sesid, tableid, columnid, new IntPtr(pointer + dataOffset), dataSize, out actualDataSize, grbit, retinfo));
                }
            }
        }
Exemplo n.º 29
0
        /// <summary>
        /// Deserialize an object from a column.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The table to read from.</param>
        /// <param name="columnid">The column to read from.</param>
        /// <param name="grbit">The retrieval options to use.</param>
        /// <returns>The deserialized object. Null if the column was null.</returns>
        public static object DeserializeObjectFromColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
        {
            int actualSize;

            if (JET_wrn.ColumnNull == Api.JetRetrieveColumn(sesid, tableid, columnid, null, 0, out actualSize, grbit, null))
            {
                return(null);
            }

            using (var stream = new ColumnStream(sesid, tableid, columnid))
            {
                var deseriaizer = new BinaryFormatter();
                return(deseriaizer.Deserialize(stream));
            }
        }
Exemplo n.º 30
0
 /// <summary>
 /// Retrieves a boolean column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <returns>The data retrieved from the column as a boolean. Null if the column is null.</returns>
 public static bool?RetrieveColumnAsBoolean(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid)
 {
     return(RetrieveColumnAsBoolean(sesid, tableid, columnid, RetrieveColumnGrbit.None));
 }