├── .gitattributes
├── .gitignore
├── EseDump
├── App.config
├── EseDump.csproj
├── Program.cs
└── Properties
│ └── AssemblyInfo.cs
├── EseView.sln
├── EseView
├── App.config
├── App.xaml
├── App.xaml.cs
├── DBColumnRetriever.cs
├── DBReader.cs
├── DBRow.cs
├── DatabaseVirtualizedProvider.cs
├── EseView.csproj
├── IVirtualizedProvider.cs
├── MainViewModel.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── VirtualizedReadOnlyList.cs
└── XmlDump.cs
├── LICENSE.txt
├── ManagedEsent
├── Esent.Interop.dll
└── Esent.Interop.xml
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # Build results
11 | [Dd]ebug/
12 | [Dd]ebugPublic/
13 | [Rr]elease/
14 | [Rr]eleases/
15 | x64/
16 | x86/
17 | build/
18 | bld/
19 | [Bb]in/
20 | [Oo]bj/
21 |
22 | # Roslyn cache directories
23 | *.ide/
24 |
25 | # MSTest test Results
26 | [Tt]est[Rr]esult*/
27 | [Bb]uild[Ll]og.*
28 |
29 | #NUNIT
30 | *.VisualState.xml
31 | TestResult.xml
32 |
33 | # Build Results of an ATL Project
34 | [Dd]ebugPS/
35 | [Rr]eleasePS/
36 | dlldata.c
37 |
38 | *_i.c
39 | *_p.c
40 | *_i.h
41 | *.ilk
42 | *.meta
43 | *.obj
44 | *.pch
45 | *.pdb
46 | *.pgc
47 | *.pgd
48 | *.rsp
49 | *.sbr
50 | *.tlb
51 | *.tli
52 | *.tlh
53 | *.tmp
54 | *.tmp_proj
55 | *.log
56 | *.vspscc
57 | *.vssscc
58 | .builds
59 | *.pidb
60 | *.svclog
61 | *.scc
62 |
63 | # Chutzpah Test files
64 | _Chutzpah*
65 |
66 | # Visual C++ cache files
67 | ipch/
68 | *.aps
69 | *.ncb
70 | *.opensdf
71 | *.sdf
72 | *.cachefile
73 |
74 | # Visual Studio profiler
75 | *.psess
76 | *.vsp
77 | *.vspx
78 |
79 | # TFS 2012 Local Workspace
80 | $tf/
81 |
82 | # Guidance Automation Toolkit
83 | *.gpState
84 |
85 | # ReSharper is a .NET coding add-in
86 | _ReSharper*/
87 | *.[Rr]e[Ss]harper
88 | *.DotSettings.user
89 |
90 | # JustCode is a .NET coding addin-in
91 | .JustCode
92 |
93 | # TeamCity is a build add-in
94 | _TeamCity*
95 |
96 | # DotCover is a Code Coverage Tool
97 | *.dotCover
98 |
99 | # NCrunch
100 | _NCrunch_*
101 | .*crunch*.local.xml
102 |
103 | # MightyMoose
104 | *.mm.*
105 | AutoTest.Net/
106 |
107 | # Web workbench (sass)
108 | .sass-cache/
109 |
110 | # Installshield output folder
111 | [Ee]xpress/
112 |
113 | # DocProject is a documentation generator add-in
114 | DocProject/buildhelp/
115 | DocProject/Help/*.HxT
116 | DocProject/Help/*.HxC
117 | DocProject/Help/*.hhc
118 | DocProject/Help/*.hhk
119 | DocProject/Help/*.hhp
120 | DocProject/Help/Html2
121 | DocProject/Help/html
122 |
123 | # Click-Once directory
124 | publish/
125 |
126 | # Publish Web Output
127 | *.[Pp]ublish.xml
128 | *.azurePubxml
129 | # TODO: Comment the next line if you want to checkin your web deploy settings
130 | # but database connection strings (with potential passwords) will be unencrypted
131 | *.pubxml
132 | *.publishproj
133 |
134 | # NuGet Packages
135 | *.nupkg
136 | # The packages folder can be ignored because of Package Restore
137 | **/packages/*
138 | # except build/, which is used as an MSBuild target.
139 | !**/packages/build/
140 | # If using the old MSBuild-Integrated Package Restore, uncomment this:
141 | #!**/packages/repositories.config
142 |
143 | # Windows Azure Build Output
144 | csx/
145 | *.build.csdef
146 |
147 | # Windows Store app package directory
148 | AppPackages/
149 |
150 | # Others
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file
167 | # to a newer Visual Studio version. Backup files are not needed,
168 | # because we have git ;-)
169 | _UpgradeReport_Files/
170 | Backup*/
171 | UpgradeLog*.XML
172 | UpgradeLog*.htm
173 |
174 | # SQL Server files
175 | *.mdf
176 | *.ldf
177 |
178 | # Business Intelligence projects
179 | *.rdl.data
180 | *.bim.layout
181 | *.bim_*.settings
182 |
183 | # Microsoft Fakes
184 | FakesAssemblies/
185 |
186 | # =========================
187 | # Operating System Files
188 | # =========================
189 |
190 | # OSX
191 | # =========================
192 |
193 | .DS_Store
194 | .AppleDouble
195 | .LSOverride
196 |
197 | # Thumbnails
198 | ._*
199 |
200 | # Files that might appear on external disk
201 | .Spotlight-V100
202 | .Trashes
203 |
204 | # Directories potentially created on remote AFP share
205 | .AppleDB
206 | .AppleDesktop
207 | Network Trash Folder
208 | Temporary Items
209 | .apdisk
210 |
211 | # Windows
212 | # =========================
213 |
214 | # Windows image file caches
215 | Thumbs.db
216 | ehthumbs.db
217 |
218 | # Folder config file
219 | Desktop.ini
220 |
221 | # Recycle Bin used on file shares
222 | $RECYCLE.BIN/
223 |
224 | # Windows Installer files
225 | *.cab
226 | *.msi
227 | *.msm
228 | *.msp
229 |
230 | # Windows shortcuts
231 | *.lnk
232 |
--------------------------------------------------------------------------------
/EseDump/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EseDump/EseDump.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {4224123C-33C5-4CA5-9413-9AF9566C6A64}
8 | Exe
9 | Properties
10 | EseDump
11 | EseDump
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\ManagedEsent\Esent.Interop.dll
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | {0110503b-fd68-494e-96ef-1945519cef30}
57 | EseView
58 |
59 |
60 |
61 |
68 |
--------------------------------------------------------------------------------
/EseDump/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace EseDump
8 | {
9 | class Program
10 | {
11 | static void Usage()
12 | {
13 | var assembly = System.Reflection.Assembly.GetEntryAssembly().GetName();
14 | Console.WriteLine("{0} version {1}", assembly.Name, assembly.Version);
15 | Console.WriteLine("usage: {0}.exe [/recover] [[/] [...]]", assembly.Name);
16 | }
17 |
18 | static async Task Run(IEnumerable args)
19 | {
20 | var vm = new EseView.MainViewModel();
21 | bool recover = false;
22 |
23 | string dbPath = args.First();
24 | args = args.Skip(1);
25 |
26 | if (args.FirstOrDefault() == "/recover")
27 | {
28 | recover = true;
29 | args = args.Skip(1);
30 | }
31 |
32 | try
33 | {
34 | await vm.OpenDatabaseAsync(dbPath, recover);
35 | }
36 | catch (Microsoft.Isam.Esent.Interop.EsentDatabaseDirtyShutdownException)
37 | {
38 | Console.WriteLine("The database was not shut down cleanly.");
39 | Console.WriteLine("Use the /recover flag to enable recovery.");
40 | Usage();
41 | return -1;
42 | }
43 | catch (Exception ex)
44 | {
45 | Console.WriteLine("Error loading database: " + ex.Message);
46 | return -2;
47 | }
48 |
49 | List tables = args.ToList();
50 | if (tables.Count == 0)
51 | {
52 | tables = vm.Tables;
53 | }
54 |
55 | using (var output = Console.OpenStandardOutput())
56 | {
57 | vm.DumpTable(tables, output);
58 | }
59 |
60 | return 0;
61 | }
62 |
63 | static void Main(string[] args)
64 | {
65 | if (args.Length >= 1)
66 | {
67 | Environment.Exit(Run(args).Result);
68 | }
69 | else
70 | {
71 | Usage();
72 | Environment.Exit(1);
73 | }
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/EseDump/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("EseDump")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("EseDump")]
13 | [assembly: AssemblyCopyright("Copyright © William R. Fraser 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("4224123c-33c5-4ca5-9413-9af9566c6a64")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.1.3.0")]
36 | [assembly: AssemblyFileVersion("1.1.3.0")]
37 |
--------------------------------------------------------------------------------
/EseView.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.22823.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EseView", "EseView\EseView.csproj", "{0110503B-FD68-494E-96EF-1945519CEF30}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EseDump", "EseDump\EseDump.csproj", "{4224123C-33C5-4CA5-9413-9AF9566C6A64}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {0110503B-FD68-494E-96EF-1945519CEF30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {0110503B-FD68-494E-96EF-1945519CEF30}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {0110503B-FD68-494E-96EF-1945519CEF30}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {0110503B-FD68-494E-96EF-1945519CEF30}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {4224123C-33C5-4CA5-9413-9AF9566C6A64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {4224123C-33C5-4CA5-9413-9AF9566C6A64}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {4224123C-33C5-4CA5-9413-9AF9566C6A64}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {4224123C-33C5-4CA5-9413-9AF9566C6A64}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/EseView/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EseView/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/EseView/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace EseView
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/EseView/DBColumnRetriever.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Microsoft.Isam.Esent.Interop;
7 | using Esent = Microsoft.Isam.Esent.Interop.Api;
8 |
9 | namespace EseView
10 | {
11 | public delegate object DBColumnRetriever(JET_SESID sesid, JET_TABLEID table, JET_COLUMNID column);
12 |
13 | public static class ColumnRetrievers
14 | {
15 | private static Dictionary s_fetchers = new Dictionary
16 | {
17 | { typeof(string), Esent.RetrieveColumnAsString },
18 | { typeof(long?), (s,t,c) => Esent.RetrieveColumnAsInt64(s,t,c) },
19 | { typeof(ulong?), (s,t,c) => Esent.RetrieveColumnAsUInt64(s,t,c) },
20 | { typeof(int?), (s,t,c) => Esent.RetrieveColumnAsInt32(s,t,c) },
21 | { typeof(uint?), (s,t,c) => Esent.RetrieveColumnAsUInt32(s,t,c) },
22 | { typeof(short?), (s,t,c) => Esent.RetrieveColumnAsInt16(s,t,c) },
23 | { typeof(ushort?), (s,t,c) => Esent.RetrieveColumnAsUInt16(s,t,c) },
24 | { typeof(byte?), (s,t,c) => Esent.RetrieveColumnAsByte(s,t,c) },
25 | { typeof(bool?), (s,t,c) => Esent.RetrieveColumnAsBoolean(s,t,c) },
26 | { typeof(double?), (s,t,c) => Esent.RetrieveColumnAsDouble(s,t,c) },
27 | { typeof(float?), (s,t,c) => Esent.RetrieveColumnAsFloat(s,t,c) },
28 |
29 | { typeof(DateTime?), (s,t,c) => Esent.RetrieveColumnAsDateTime(s,t,c) },
30 | { typeof(Guid?), (s,t,c) => Esent.RetrieveColumnAsGuid(s,t,c) },
31 | { typeof(byte[]), Esent.RetrieveColumn },
32 |
33 | };
34 |
35 | public static DBColumnRetriever ForType(Type t)
36 | {
37 | if (!s_fetchers.ContainsKey(t))
38 | {
39 | return (x, y, z) => "Error: unhandled type.";
40 | }
41 |
42 | return s_fetchers[t];
43 | }
44 |
45 | public static T Retrieve(JET_SESID sesid, JET_TABLEID table, JET_COLUMNID column)
46 | {
47 | return (T)ForType(typeof(T))(sesid, table, column);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/EseView/DBReader.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Isam.Esent.Interop;
2 | using Microsoft.Isam.Esent.Interop.Vista;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using Esent = Microsoft.Isam.Esent.Interop.Api;
7 |
8 | namespace EseView
9 | {
10 | public class DBReader : IDisposable
11 | {
12 | private Instance m_jetInstance;
13 | private Session m_sesid;
14 | private JET_DBID m_dbid;
15 | private string m_filename;
16 | private Dictionary> m_tableDefs;
17 | private Dictionary, IEnumerable> m_indexDefs;
18 |
19 | struct ColSpec
20 | {
21 | public string Name;
22 | public Type Type;
23 | public DBColumnRetriever Retriever;
24 | public JET_COLUMNID ColumnId;
25 | }
26 |
27 | public DBReader(string filename)
28 | {
29 | m_filename = filename;
30 | m_tableDefs = new Dictionary>();
31 | m_indexDefs = new Dictionary, IEnumerable>();
32 | m_dbid = JET_DBID.Nil;
33 | }
34 |
35 | public void Init(bool recoveryEnabled)
36 | {
37 | int pageSize;
38 | Esent.JetGetDatabaseFileInfo(m_filename, out pageSize, JET_DbInfo.PageSize);
39 |
40 | string dir = Path.GetDirectoryName(m_filename) + Path.DirectorySeparatorChar;
41 | Esent.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.DatabasePageSize, pageSize, null);
42 | Esent.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.LogFilePath, 0, dir);
43 | Esent.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.SystemPath, 0, dir);
44 |
45 | // Put the temp DB in our working directory.
46 | Esent.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.TempPath, 0, Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar);
47 |
48 | // Set recovery option.
49 | Esent.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.Recovery, 0, recoveryEnabled ? "On" : "Off");
50 |
51 | m_jetInstance = new Instance("ESEVIEW");
52 | m_jetInstance.Init();
53 |
54 | m_sesid = new Session(m_jetInstance);
55 |
56 | Esent.JetAttachDatabase(m_sesid, m_filename, recoveryEnabled ? AttachDatabaseGrbit.None : AttachDatabaseGrbit.ReadOnly);
57 | Esent.JetOpenDatabase(m_sesid, m_filename, null, out m_dbid, OpenDatabaseGrbit.ReadOnly);
58 | }
59 |
60 | ~DBReader()
61 | {
62 | Close();
63 | }
64 |
65 | public void Dispose()
66 | {
67 | Close();
68 | }
69 |
70 | public void Close()
71 | {
72 | if ((m_sesid != null) && (m_sesid.JetSesid != JET_SESID.Nil))
73 | {
74 | if (!m_dbid.Equals(JET_DBID.Nil))
75 | {
76 | Esent.JetCloseDatabase(m_sesid, m_dbid, CloseDatabaseGrbit.None);
77 | }
78 | m_sesid.End();
79 | }
80 |
81 | if ((m_jetInstance != null) && !m_jetInstance.Equals(JET_INSTANCE.Nil))
82 | {
83 | m_jetInstance.Close();
84 | }
85 | }
86 |
87 | public IEnumerable Tables
88 | {
89 | get
90 | {
91 | return Esent.GetTableNames(m_sesid, m_dbid);
92 | }
93 | }
94 |
95 | public int GetRowCount(string tableName, string indexName = null)
96 | {
97 | if (string.IsNullOrEmpty(tableName))
98 | return 0;
99 |
100 | using (var table = new Table(m_sesid, m_dbid, tableName, OpenTableGrbit.ReadOnly))
101 | {
102 | if (!string.IsNullOrEmpty(indexName))
103 | {
104 | // This is needed because an index can be over a nullable column and exclude
105 | // the nulls, resulting in fewer records than when not using the index.
106 | Esent.JetSetCurrentIndex2(m_sesid, table, indexName, SetCurrentIndexGrbit.MoveFirst);
107 | }
108 |
109 | int numRecords;
110 | Esent.JetIndexRecordCount(m_sesid, table, out numRecords, 0);
111 | return numRecords;
112 | }
113 | }
114 |
115 | private void LoadTableDef(string tableName)
116 | {
117 | using (var table = new Table(m_sesid, m_dbid, tableName, OpenTableGrbit.ReadOnly))
118 | {
119 | m_tableDefs[tableName] = GetTableDef(table);
120 | }
121 | }
122 |
123 | private List GetTableDef(JET_TABLEID table)
124 | {
125 | var columns = new List(Esent.GetTableColumns(m_sesid, table));
126 | var tableDef = new List();
127 |
128 | foreach (var column in columns)
129 | {
130 | var colspec = new ColSpec();
131 | colspec.Name = column.Name;
132 | colspec.ColumnId = column.Columnid;
133 | colspec.Retriever = null;
134 |
135 | switch (column.Coltyp)
136 | {
137 | case JET_coltyp.Text:
138 | case JET_coltyp.LongText:
139 | colspec.Type = typeof(string);
140 | break;
141 | case JET_coltyp.Long:
142 | colspec.Type = typeof(int?);
143 | break;
144 | case JET_coltyp.Short:
145 | colspec.Type = typeof(short?);
146 | break;
147 | case JET_coltyp.UnsignedByte:
148 | colspec.Type = typeof(byte?);
149 | break;
150 | case JET_coltyp.Bit:
151 | colspec.Type = typeof(bool?);
152 | break;
153 | case JET_coltyp.DateTime:
154 | colspec.Type = typeof(DateTime?);
155 | break;
156 | case JET_coltyp.IEEEDouble:
157 | colspec.Type = typeof(double?);
158 | break;
159 | case JET_coltyp.IEEESingle:
160 | colspec.Type = typeof(float?);
161 | break;
162 | case JET_coltyp.Binary:
163 | case JET_coltyp.LongBinary:
164 | colspec.Retriever = (s, t, c) =>
165 | {
166 | byte[] value = Esent.RetrieveColumn(s, t, c);
167 | if (value != null)
168 | return Convert.ToBase64String(value);
169 | else
170 | return value;
171 | };
172 | colspec.Type = typeof(string);
173 | break;
174 | case VistaColtyp.UnsignedLong:
175 | colspec.Type = typeof(UInt32?);
176 | break;
177 | case VistaColtyp.LongLong:
178 | colspec.Type = typeof(Int64?);
179 | break;
180 | case VistaColtyp.GUID:
181 | colspec.Type = typeof(Guid?);
182 | break;
183 | case VistaColtyp.UnsignedShort:
184 | colspec.Type = typeof(UInt16?);
185 | break;
186 | default:
187 | colspec.Retriever = (s, t, c) => "ERROR: unhandled type " + Enum.GetName(typeof(JET_coltyp), column.Coltyp) + "(" + (int)column.Coltyp + ")";
188 | colspec.Type = typeof(string);
189 | break;
190 | }
191 |
192 | if (colspec.Retriever == null)
193 | {
194 | colspec.Retriever = ColumnRetrievers.ForType(colspec.Type);
195 | }
196 |
197 | tableDef.Add(colspec);
198 | }
199 |
200 | return tableDef;
201 | }
202 |
203 | public IEnumerable> GetColumnNamesAndTypes(string tableName)
204 | {
205 | if (string.IsNullOrEmpty(tableName))
206 | {
207 | yield break;
208 | }
209 |
210 | if (!m_tableDefs.ContainsKey(tableName))
211 | {
212 | LoadTableDef(tableName);
213 | }
214 |
215 | foreach (var colspec in m_tableDefs[tableName])
216 | {
217 | yield return new KeyValuePair(colspec.Name, colspec.Type);
218 | }
219 | }
220 |
221 | public IEnumerable> GetRows(string tableName, string indexName = null, int startRow = 0, int rowCount = -1)
222 | {
223 | if (!m_tableDefs.ContainsKey(tableName))
224 | LoadTableDef(tableName);
225 |
226 | using (var table = new Table(m_sesid, m_dbid, tableName, OpenTableGrbit.ReadOnly))
227 | {
228 | var colspec = new List>();
229 |
230 | try
231 | {
232 | Esent.JetSetCurrentIndex2(m_sesid, table, indexName, SetCurrentIndexGrbit.MoveFirst);
233 |
234 | if (startRow != 0)
235 | {
236 | Esent.JetMove(m_sesid, table, startRow, MoveGrbit.None);
237 | }
238 | }
239 | catch (EsentNoCurrentRecordException)
240 | {
241 | // Return an empty set.
242 | yield break;
243 | }
244 |
245 | int rowNumber = 0;
246 | do
247 | {
248 | var values = new List