mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2026-04-06 15:05:50 +00:00
Version 4.3.0. Changed FileDbCache folder structure. New UWP project files.
This commit is contained in:
parent
a7bb9e1ef4
commit
2f123886ff
31 changed files with 184 additions and 256 deletions
983
FileDbCache/FileDb/Help.html
Normal file
983
FileDbCache/FileDb/Help.html
Normal file
|
|
@ -0,0 +1,983 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-au">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>FileDb Overview</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<b>
|
||||
<p><font face="Arial" size="4" color="#0066CC">Overview</font></p>
|
||||
</b>
|
||||
<p><font face="Arial">FileDb is a simple database designed as a simple
|
||||
local database solution for Xamarin Cross-Platform phone (Android, IOS, WinPhone)
|
||||
or any .NET application. <u>FileDb is a No-SQL database</u>
|
||||
meant for use as a local data store for applications.
|
||||
Here are some important points about FileDb:</font></p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<font face="Arial">Stores one table per file, including its index</font></li>
|
||||
<li>
|
||||
<font face="Arial">Extremely Lightweight - less than 50K</font></li>
|
||||
<li>
|
||||
<font face="Arial">Supports field types Int, UInt, Bool, String, Byte,
|
||||
Float, Double and DateTime and also arrays of the same
|
||||
types</font></li>
|
||||
<li>
|
||||
<font face="Arial">Index supports a single Primary Key field (optional)</font></li>
|
||||
<li>
|
||||
<font face="Arial">Compiled versions for Windows Phone
|
||||
RT/PCL,
|
||||
.NET</font></li>
|
||||
<li>
|
||||
<font face="Arial">FileDb is VERY FAST</font></li>
|
||||
<li>
|
||||
<font face="Arial">FileDb is FREE to use in your applications</font></li>
|
||||
<li>
|
||||
<font face="Arial">Use with LINQ to Objects to achieve full relational
|
||||
capability</font></li>
|
||||
</ul>
|
||||
|
||||
<p><font face="Arial">FileDb was specifically designed to use only native
|
||||
.NET data types so there would no need to translate
|
||||
between database storage and the CLR data types.
|
||||
So you can just as easily read/write a String[] field as
|
||||
you would an Int field. Another feature is that a
|
||||
database file created on any .NET platform will work on
|
||||
any other. So you can create a database file on
|
||||
your Windows machine and it can be used in a Silverlight
|
||||
or Windows Phone app.</font></p>
|
||||
|
||||
<p><font color="#0066CC" face="Arial"><b>LINQ + FileDb gives you full
|
||||
relational database capability</b></font></p>
|
||||
<p><font face="Arial">Even though FileDb is a "flat-file" database, using
|
||||
LINQ it becomes fully relational! LINQ
|
||||
to Objects allows you to join Tables together just as
|
||||
you would do in SQL. All of the power of LINQ is
|
||||
available to you: Joins, Grouping, Sum - the lot.
|
||||
(See
|
||||
the examples below.)</font></p>
|
||||
<p><font face="Arial">FileDb also has a built-in
|
||||
query filter parser so you can write SQL-like
|
||||
filter expressions to make filtering data easy, like
|
||||
this:</font></p>
|
||||
<blockquote>
|
||||
<p><b>
|
||||
<font color="#663300" face="Courier New" size="2">
|
||||
string filter = "FirstName IN ('Cindy', 'John') AND Age > 32"</font></b></p>
|
||||
</blockquote>
|
||||
<p><font face="Arial">Use FileDb in your .NET and mobile
|
||||
applications where you need a searchable, updatable
|
||||
local database.</font><p>
|
||||
<b><font face="Arial" color="#0066CC">Use FileDb with Xamarin cross-platform app
|
||||
development</font></b><p><font face="Arial">Most phone apps only require a
|
||||
simple database. By purchasing a source code license you can compile
|
||||
FileDb into your IOS, Android and Windows Phone projects and use the same exact
|
||||
data layer code for them all. This is much easier than using Sqlite
|
||||
wrappers. With FileDb's built in encryption you can have everything you
|
||||
need to have a secure data layer.</font></p>
|
||||
<p>
|
||||
<font color="#0066CC" face="Arial"><b>FileDb Database Overview</b></font></p>
|
||||
|
||||
<p><font face="Arial">FileDb is a simple database designed for use on any .NET platform such as Windows
|
||||
Phone and Silverlight, but its also great for any .NET app where simple local
|
||||
database storage is needed. For example, instead of using XML config files you
|
||||
could use a FileDb database to store and retrieve application data much more
|
||||
efficiently. FileDb allows only a single table per database file, so when we
|
||||
talk about a FileDb database we really mean a single table with an index. The
|
||||
index is stored in the file with the data, and allows an optional Primary Key.</font></p>
|
||||
<p><font face="Arial">FileDb is NOT a relational database - it is NO-SLQ,
|
||||
meaning you can't directly issue SQL commands for querying, adding or updating. However,
|
||||
you CAN use LINQ with
|
||||
FileDb to get full relational query capabilities. And FileDb does include an Expression Parser which parses SQL-like filter
|
||||
expressions, which makes searching, updating and deleting very easy - see below for an example.</font></p>
|
||||
<p><font face="Arial"><u>And FileDb supports using powerful Regular Expressions for
|
||||
filtering.</u></font></p>
|
||||
<p><font face="Arial"><u>FileDb supports AES encryption</u> at the record level. This
|
||||
means the database schema is not encrypted (field names, etc.), but each record
|
||||
is entirely encrypted. Encryption is "all or nothing", meaning it expects that
|
||||
either all records are encrypted or all records are not encrypted. You turn
|
||||
encryption on by passing an encryption key when opening the database.</font></p>
|
||||
<u>
|
||||
<p dir="ltr"><font face="Arial">FileDb is thread-safe for multithreading environments, so it can be accessed from
|
||||
multiple threads at the same time without worrying about database corruption.</font></u></p>
|
||||
<p><font face="Arial">FileDb databases can only be opened by a single
|
||||
application. Any attempt to open the file when already open will fail.
|
||||
This makes sense since its meant for use by a single application at a time
|
||||
(FileDb is not meant as a multi-user database, such as SQL Server Express).<br>
|
||||
</font></p>
|
||||
<p><b><font color="#0066CC" face="Arial">FileDb Classes</font></b></p>
|
||||
<p><font face="Arial">The main FileDb classes are: <b>FileDb</b>, <b>Table</b>,
|
||||
<b>Field</b> and <b>Record</b>. </font> </p>
|
||||
<dir>
|
||||
<b>
|
||||
<li><font face="Arial">FileDb</font></b><font face="Arial">: Represents a database file. All database operations are
|
||||
initiated through this class.<br>
|
||||
</li>
|
||||
</font>
|
||||
<b>
|
||||
<li><font face="Arial">Table</font></b><font face="Arial">: Represents a two
|
||||
dimensional dataset returned from a query. A Table consists of <b>Fields </b>
|
||||
and <b>Records</b>.<br>
|
||||
</li>
|
||||
</font>
|
||||
<b>
|
||||
<li><font face="Arial">Field</font></b><font face="Arial">: Defines the
|
||||
properties of the table column, such as Name and DataType.<br>
|
||||
</li>
|
||||
</font>
|
||||
<b>
|
||||
<li><font face="Arial">Fields</font></b><font face="Arial">: A List of Field
|
||||
objects.<br>
|
||||
</font></li>
|
||||
<li>
|
||||
<font face="Arial">
|
||||
<b>
|
||||
Record</b>: A list of data objects represents a single row in a Table.
|
||||
Implements IEnumerable and the Data property which is used for DataBinding.<br>
|
||||
</li>
|
||||
</font>
|
||||
<b>
|
||||
<li><font face="Arial">Records</font></b><font face="Arial">: A List of
|
||||
Record objects.<br>
|
||||
</li>
|
||||
</font>
|
||||
<b>
|
||||
<li><font face="Arial">FieldValues</font></b><font face="Arial">: A simple
|
||||
Name/Value pair Dictionary. Use this class when adding and updating records.<br>
|
||||
</li>
|
||||
</font>
|
||||
<b>
|
||||
<li><font face="Arial">FilterExpression</font></b><font face="Arial">: Used
|
||||
to filter records for query, update and delete.<br>
|
||||
</li>
|
||||
</font>
|
||||
<b>
|
||||
<li><font face="Arial">FilterExpressionGroup</font></b><font face="Arial">:
|
||||
Used to create compound expressions by grouping FilterExpressions and
|
||||
FilterExpressionGroups.<br>
|
||||
</font></li>
|
||||
</dir>
|
||||
<p><b><font color="#0066CC" face="Arial">Database Fields</font></b></p>
|
||||
<p><font face="Arial">Fields (or Columns) can be of several common types:
|
||||
String, Int, UInt, Bool, Byte, Float, Double and DateTime, or can also be an array of any of
|
||||
these types.</font></p>
|
||||
<p><font face="Arial">Int Fields can be AutoIncrementing, and you can optionally
|
||||
specify one field to be Primary Key (it must be of type Int or String).</font></p>
|
||||
<p><font face="Arial">FileDb doesn't support the notion of NULL fields for the
|
||||
non-array type. Only array type fields can have NULL values. The non-array field
|
||||
values will always have a value, either zero or empty.</font></p>
|
||||
<p><font color="#0066CC" face="Arial"><b>FileDb Records</b></font></p>
|
||||
<p><font face="Arial">FileDb supports two methods of data retrieval. You can say the
|
||||
"default" way is with the built-in Record and Records classes. Think of
|
||||
Record as the .NET DataRow class, and think of Table as a DataTable. Table
|
||||
is a list of Records, and a Record holds the actual values. You access Field
|
||||
values using indexing just as you would a DataRow, like this:</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" width="100%" id="table25" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<font face="Courier New" size="2">FileDb employeesDb = new FileDb();<br>
|
||||
employeesDb.Open( Employees.fdb" );<br>
|
||||
<br>
|
||||
Table employees = employeesDb.SelectAllRecords();<br>
|
||||
Record record =
|
||||
employees[0];<br>
|
||||
int id = (int) record["EmployeeId"];<br>
|
||||
// or<br>
|
||||
id
|
||||
= (int) record[0];</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p><font face="Arial">To use a Table with LINQ, you do this:</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" width="100%" id="table26" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<font FACE="Courier New" size="2">var recs = from e in
|
||||
employees<br>
|
||||
where (string)
|
||||
e["FirstName"] == "John"<br>
|
||||
select e;</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p><font face="Arial">Notice we have to cast the record value to a string.
|
||||
This is because, just like with the DataRow, Record
|
||||
values are all type object.</font></p>
|
||||
<p><font color="#0066CC" face="Arial"><b>Records and Custom Objects</b></font></p>
|
||||
<p><font face="Arial">Records are great because they require no additional
|
||||
programming and they work with LINQ, albeit with some
|
||||
casting. But you can use your own custom classes
|
||||
if you want because FileDb has template (generic)
|
||||
overloads for each of the SelectRecords methods.
|
||||
You only need to create a class with public properties
|
||||
which match the names of the fields you want to use.
|
||||
Here's an example using the Employees table.</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" width="100%" id="table27" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<font FACE="Courier New" size="2">public class Employee<br>
|
||||
{<br>
|
||||
public int EmployeeID { get; set; }<br>
|
||||
public string LastName { get; set; }<br>
|
||||
|
||||
public string
|
||||
FirstName { get; set; }<br>
|
||||
|
||||
public string Title {
|
||||
get; set; }<br>
|
||||
|
||||
public string
|
||||
TitleOfCourtesy { get; set; }<br>
|
||||
|
||||
public DateTime
|
||||
BirthDate { get; set; }<br>
|
||||
|
||||
public DateTime
|
||||
HireDate { get; set; }<br>
|
||||
|
||||
public string Address
|
||||
{ get; set; }<br>
|
||||
|
||||
public string City {
|
||||
get; set; }<br>
|
||||
|
||||
public string Region {
|
||||
get; set; }<br>
|
||||
|
||||
public string
|
||||
PostalCode { get; set; }<br>
|
||||
|
||||
public string Country
|
||||
{ get; set; }<br>
|
||||
|
||||
public string
|
||||
HomePhone { get; set; }<br>
|
||||
|
||||
public string
|
||||
Extension { get; set; }<br>
|
||||
|
||||
public Byte[] Photo {
|
||||
get; set; }<br>
|
||||
|
||||
public string Notes {
|
||||
get; set; }<br>
|
||||
|
||||
public int ReportsTo {
|
||||
get; set; }<br>
|
||||
}</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p><font face="Arial">The templated SelectRecords versions return a IList<T>
|
||||
where T is your custom type.</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" width="100%" id="table28" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<font FACE="Courier New" size="2">
|
||||
IList<Employee>
|
||||
employees = employeesDb.SelectAllRecords<Employee>();<br>
|
||||
Employee employee
|
||||
= employees[0];<br>
|
||||
int id = Employee.EmployeeId;<br>
|
||||
<br>
|
||||
var emps = from e in
|
||||
employees<br>
|
||||
where e.FirstName
|
||||
== "John"<br>
|
||||
select e;</td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p><font face="Arial">As you can see, this is much cleaner code. And
|
||||
its actually more efficient since the Record class has
|
||||
more overhead because its not as simple.</font></p>
|
||||
<p><b><font color="#0066CC" face="Arial">Searching and Filtering</font></b></p>
|
||||
<p><font face="Arial">FileDb uses FilterExpressions and
|
||||
FilterExpressionGroups to filter records in queries and
|
||||
updates. We use FilterExpressions for simple queries
|
||||
which consist of a single field comparison (field =
|
||||
'value') and we use FilterExpressionGroups for compound
|
||||
expressions, where multiple expressions and grouping are
|
||||
required. You can add either FilterExpressions or
|
||||
FilterExpressionGroups to a FilterExpressionGroup, thus
|
||||
creating complex expresssions (FileDb processes
|
||||
FilterExpressionGroups recursively).</font></p>
|
||||
<p><font face="Arial">You can either create your own manually in code or
|
||||
use the built-in Expression Parser to create them for
|
||||
you. The Expression Parser recognizes standard SQL
|
||||
comparison operators. You can see it used in the
|
||||
examples below. It also recognizes REGEX, which
|
||||
uses Regular Expressions, and CONTAINS which uses <b>
|
||||
String.Contains</b>. See the section on
|
||||
Regular Expressions below for more info. Field names
|
||||
prefixed with ~ specifies no-case comparison (for
|
||||
strings only).</font></p>
|
||||
<p><font face="Arial">Each time you use () around an expression, a new
|
||||
FilterExpressionGroup will be created. The inner-most expressions are evaluated
|
||||
first, just as in SQL.</font></p>
|
||||
<b>
|
||||
<p><font color="#333333" face="Arial">Example 1: Create a FilterExpression</font></p>
|
||||
</b>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" width="100%" id="table29" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<font size="2" FACE="Courier New">// build an expression manually<br>
|
||||
FilterExpression searchExp = new FilterExpression( "LastName", "Peacock",
|
||||
Equality.Equal );<br>
|
||||
<br>
|
||||
// build the same expression using the
|
||||
parser<br>
|
||||
searchExp = FilterExpression.Parse( "LastName = 'Peacock'" ); <br>
|
||||
Table table = employeesDb.SelectRecords(
|
||||
searchExp,
|
||||
new string[] { "ID", "LastName" } );<br>
|
||||
<br>
|
||||
// Or you can simply pass the string filter
|
||||
directly - a FilterExpression will be
|
||||
created in the same way as above<br>
|
||||
<br>
|
||||
table = employeesDb.SelectRecords( "LastName
|
||||
= 'Peacock'", new string[] { "ID", "LastName"
|
||||
} );<br>
|
||||
<br>
|
||||
foreach( Record record in table )<br>
|
||||
{<br>
|
||||
foreach( object value in record )<br>
|
||||
{<br>
|
||||
|
||||
Debug.WriteLine( value );<br>
|
||||
|
||||
}<br>
|
||||
}</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<b>
|
||||
<p><font color="#333333" face="Arial"><br>
|
||||
Example 2: Create a FilterExpressionGroup</font></p>
|
||||
</b>
|
||||
<p><font face="Arial">This example creates two identical FilterExpressionGroups,
|
||||
one using the Expression Parser and the other with code.</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" width="100%" id="table30" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font size="2" FACE="Courier New">// For string fields there are
|
||||
2 ways to specify </font><font size="2" FACE="Courier New">no-case
|
||||
comparisons: you can prefix fieldnames with ~ or you can use ~= as
|
||||
demonstrated below<br>
|
||||
// The first form is needed when using the IN operator, eg.<br>
|
||||
FilterExpressionGroup filterExpGrp =
|
||||
FilterExpressionGroup.Parse( "(FirstName ~= 'andrew' OR ~FirstName = 'nancy')
|
||||
AND LastName = 'Fuller'" );<br>
|
||||
Table table = employeesDb.SelectRecords( filterExpGrp );<br>
|
||||
<br>
|
||||
// equivalent building it manually<br>
|
||||
var fname1Exp = new FilterExpression( "FirstName", "andrew", Equality.Equal,
|
||||
MatchType.IgnoreCase );<br>
|
||||
var fname2Exp = new FilterExpression( "FirstName", "nancy", Equality.Equal,
|
||||
MatchType.IgnoreCase );<br>
|
||||
var lnameExp = new FilterExpression( "LastName", "Fuller", Equality.Equal );
|
||||
// this constructor defaults to MatchType.UseCase<br>
|
||||
var fnamesGrp = new FilterExpressionGroup();<br>
|
||||
fnamesGrp.Add( BoolOp.Or, fname1Exp );<br>
|
||||
fnamesGrp.Add( BoolOp.Or, fname2Exp );<br>
|
||||
var allNamesGrp = new FilterExpressionGroup();<br>
|
||||
allNamesGrp.Add( BoolOp.And, lnameExp );<br>
|
||||
allNamesGrp.Add( BoolOp.And, fnamesGrp );<br>
|
||||
<br>
|
||||
table = employeesDb.SelectRecords( allNamesGrp );<br>
|
||||
<br>
|
||||
// or just pass the filter string directly<br>
|
||||
<br>
|
||||
table = employeesDb.SelectRecords( "(FirstName ~= 'andrew' OR ~FirstName = 'nancy')
|
||||
AND LastName = 'Fuller'" );<br>
|
||||
</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p><font face="Arial"><br>
|
||||
FileDb supports these comparison operators:</font></p>
|
||||
<font face="Arial" size="2">
|
||||
<font face="Courier New">
|
||||
<blockquote>
|
||||
<table border="0" id="table31" style="border-collapse: collapse" bgcolor="#FBEDBB" cellpadding="7">
|
||||
<tr>
|
||||
<font face="Courier New" size="2">
|
||||
<td><b>=</b></td>
|
||||
</font><font face="Arial" size="2">
|
||||
<td width="18"> </td>
|
||||
<font face="Courier New">
|
||||
<td><font face="Arial">Equality</font></td>
|
||||
</font></font>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>~<b>=</b></td>
|
||||
</font><font face="Arial">
|
||||
<td width="18"> </td>
|
||||
<font face="Courier New">
|
||||
<td>No-case equality - strings only</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font face="Courier New"><b><></b></font></td>
|
||||
</font><font face="Arial">
|
||||
<td width="18"> </td>
|
||||
<font face="Courier New">
|
||||
<td><font face="Arial">Not Equal</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font face="Courier New"><b>!=</b></font></td>
|
||||
</font><font face="Arial">
|
||||
<td width="18"> </td>
|
||||
<font face="Courier New">
|
||||
<td><font face="Arial">Not Equal (same as <>)</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font face="Courier New"><b>>=</b></font></td>
|
||||
</font><font face="Arial">
|
||||
<td width="18"> </td>
|
||||
<font face="Courier New">
|
||||
<td><font face="Arial">Greater than or Equal</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font face="Courier New"><b><=</b></font></td>
|
||||
</font><font face="Arial">
|
||||
<td width="18"> </td>
|
||||
<font face="Courier New">
|
||||
<td><font face="Arial">Less than or Equal</font></td>
|
||||
</tr>
|
||||
</font>
|
||||
<font face="Courier New" size="2">
|
||||
<tr>
|
||||
<td><b><font face="Courier New">REGEX</font></b></td>
|
||||
</font>
|
||||
</font>
|
||||
<font face="Arial" size="2">
|
||||
<font face="Arial">
|
||||
<td width="18"> </td>
|
||||
<td><font face="Arial">Use Regular Expression</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<font face="Arial" size="2">
|
||||
<td><b><font face="Courier New">CONTAINS</font></b></td>
|
||||
<font face="Arial">
|
||||
<td width="18"> </td>
|
||||
<td><font face="Arial">Use the .NET String's Contains method</font></td>
|
||||
</font>
|
||||
</font>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><font face="Courier New">IN</font></b></td>
|
||||
<td width="18"> </td>
|
||||
<td><font face="Arial">Creates a HashSet of values to use like SQL
|
||||
IN operator</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<font face="Arial" size="2">
|
||||
<td><b><font face="Courier New">NOT</font></b></td>
|
||||
<font face="Arial">
|
||||
<td width="18"> </td>
|
||||
<td><font face="Arial">Logical Negation, e.g NOT CONTAINS</font></td>
|
||||
</font>
|
||||
</font>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
</font>
|
||||
</font>
|
||||
</font></font></font></font></font>
|
||||
<font face="Arial" size="2">
|
||||
<p> </p>
|
||||
</font>
|
||||
<p><b><font face="Arial" color="#0066CC">REGEX - </font>
|
||||
<font color="#0066CC" face="Arial" size="3">Regular Expressions in searches and filtering</font></b></p>
|
||||
<p><font face="Arial" size="3">FileDb supports using Regular Expressions. You can use any RegEx supported by
|
||||
.NET. The Expression Parser supports MatchType.RegEx using the REGEX operator.
|
||||
Internally, FileDb uses FilterExpressions to evaluate fields. You don't
|
||||
need to use them because you can pass in filter strings and they'll be parsed
|
||||
into FilterExpressions/FilterExpressionGroups for you. This is just to
|
||||
show you how can create them manually if you want to. In
|
||||
the example below, both FilterExpressionGroups are identical.</font></p>
|
||||
<font FACE="Courier New" size="2">
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" id="table32" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font size="2" FACE="Courier New">// Using the Expression Parser<br>
|
||||
<br>
|
||||
// You can use brackets around fieldnames if there are spaces in the
|
||||
name<br>
|
||||
FilterExpressionGroup filterExpGrp = FilterExpressionGroup.Parse( "(~FirstName = 'steven' OR [FirstName]
|
||||
REGEX 'NANCY') AND LastName = 'Fuller'" );<br>
|
||||
Table table = employeesDb.SelectRecords( filterExpGrp );<br>
|
||||
<br>
|
||||
// we can manually build the same FilterExpressionGroup<br>
|
||||
var fname1Exp = FilterExpression.Parse( "~FirstName = steven" );<br>
|
||||
var fname2Exp = new FilterExpression( "FirstName", "NANCY", Equality.Regex );<br>
|
||||
var lnameExp = new FilterExpression( "LastName", "Fuller", Equality.Equal );<br>
|
||||
var fnamesGrp = new FilterExpressionGroup();<br>
|
||||
fnamesGrp.Add( BoolOp.Or, fname1Exp );<br>
|
||||
fnamesGrp.Add( BoolOp.Or, fname2Exp );<br>
|
||||
var allNamesGrp = new FilterExpressionGroup();<br>
|
||||
allNamesGrp.Add( BoolOp.And, lnameExp );<br>
|
||||
allNamesGrp.Add( BoolOp.And, fnamesGrp );<br>
|
||||
<br>
|
||||
table = employeesDb.SelectRecords( allNamesGrp );</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
</font>
|
||||
<font face="Arial" size="2">
|
||||
<p> </p>
|
||||
</font>
|
||||
<p><b><font color="#0066CC" face="Arial" size="3">Using CONTAINS in searches and filtering</font></b></p>
|
||||
<p><font face="Arial" size="3">FileDb supports using Regular Expressions. You can use any RegEx supported by
|
||||
.NET. The Expression Parser supports MatchType.RegEx using the REGEX operator.
|
||||
Internally, FileDb uses FilterExpressions to evaluate fields. You don't
|
||||
need to use them because you can pass in filter strings and they'll be parsed
|
||||
into FilterExpressions/FilterExpressionGroups for you. This is just to
|
||||
show you how can create them manually if you want to. In
|
||||
the example below, both FilterExpressionGroups are identical.</font></p>
|
||||
<font FACE="Courier New" size="2">
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" id="table42" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font size="2" FACE="Courier New">// You can use brackets around fieldnames if there are spaces in the
|
||||
name<br>
|
||||
FilterExpressionGroup filterExpGrp = FilterExpressionGroup.Parse( "(~FirstName = 'steven' OR [FirstName]
|
||||
CONTAINS 'NANC') AND LastName = 'Fuller'" );<br>
|
||||
Table table = employeesDb.SelectRecords( filterExpGrp );<br>
|
||||
<br>
|
||||
// we can manually build the same FilterExpressionGroup<br>
|
||||
var fname1Exp = FilterExpression.Parse( "~FirstName = steven" );<br>
|
||||
var fname2Exp = new FilterExpression( "FirstName", "NANCY", Equality.Contains );<br>
|
||||
var lnameExp = new FilterExpression( "LastName", "Fuller", Equality.Equal );<br>
|
||||
var fnamesGrp = new FilterExpressionGroup();<br>
|
||||
fnamesGrp.Add( BoolOp.Or, fname1Exp );<br>
|
||||
fnamesGrp.Add( BoolOp.Or, fname2Exp );<br>
|
||||
var allNamesGrp = new FilterExpressionGroup();<br>
|
||||
allNamesGrp.Add( BoolOp.And, lnameExp );<br>
|
||||
allNamesGrp.Add( BoolOp.And, fnamesGrp );<br>
|
||||
<br>
|
||||
table = employeesDb.SelectRecords( allNamesGrp );</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
</font>
|
||||
<p> </p>
|
||||
<p><b><font color="#0066CC" face="Arial" size="3">Sort Ordering</font></b></p>
|
||||
<p><font face="Arial" size="3">Query methods allow for sorting the results by fields. To
|
||||
get a reverse sort, prefix the sort field list with !. To get a no-case sort,
|
||||
prefix with ~. To get both reverse and no-case sort, use both ! and ~.</font></p>
|
||||
<p><font face="Arial" size="3">Example:</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New" size="2">
|
||||
<table border="0" id="table33" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<font FACE="Courier New" size="2">
|
||||
Table table = employeesDb.SelectAllRecords( new string[] { "ID", "Firstname", "LastName",
|
||||
"Age" }, false, new string[] { "~LastName", "~FirstName", "!Age" } );</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p><font color="#0066CC" face="Arial" size="3"><b>Selecting a Table from a Table</b></font></p>
|
||||
<p><font face="Arial" size="3">Another very powerful feature of FileDb is the ability to select a Table from
|
||||
another Table. This would allow you to be able to select data from a Table
|
||||
after the database file has been closed, for example.</font></p>
|
||||
<p><font face="Arial" size="3">Example:</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New" size="2">
|
||||
<table border="0" id="table34" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<font FACE="Courier New" size="2">
|
||||
customersDb.Open( path + "Customers.fdb" );<br>
|
||||
<br>
|
||||
// select all fields and records from the database table<br>
|
||||
Table customers = customersDb.SelectAllRecords();<br>
|
||||
<br>
|
||||
Table subCusts = customers.SelectRecords( "CustomerID <> 'ALFKI'",<br>
|
||||
new string[] { "CustomerID", "CompanyName", "City" }, new string[] { "~City", "~CompanyName"
|
||||
} );</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p><b><font color="#0066CC" face="Arial" size="3">Encryption</font></b></p>
|
||||
<p><font face="Arial" size="3">Using encryption with FileDb is simple. You only need to
|
||||
specify a string key when you open the database. After that everything is
|
||||
automatic. The only caveat is you must set a key before you add any records.
|
||||
Once a single record has been added without a key set you cannot later add
|
||||
records with a key. Its all or nothing. Likewise, you cannot add records with
|
||||
encryption and later add records without. You must set the encryption key
|
||||
each time you add any records.</font></p>
|
||||
<p><b><font color="#0066CC" face="Arial" size="3">Persisting Tables</font></b></p>
|
||||
<p><font face="Arial" size="3">You can easily save a Table as a new database using
|
||||
Table.SaveToDb. This method creates a new database file using the Fields
|
||||
in the Table then populates it using the Records in the Table. For
|
||||
example, you can select subsets of your data, save it as a new database and send
|
||||
it over the Internet.</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" id="table35" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font FACE="Courier New" size="2">Table table = employeesDb.SelectAllRecords( new string[] { "ID", "Firstname", "LastName"
|
||||
} );<br>
|
||||
table.SaveToDb( "Names.fdb" );</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p><font face="Arial" size="3">You can also save a Table to a database from the
|
||||
FileDb Explorer. Just right-click on the Grid to show
|
||||
the context menu and select the "Create database from
|
||||
Table..." menu item.<br>
|
||||
</font></p>
|
||||
<p><font color="#0066CC" face="Arial" size="3"><b>Using LINQ to Objects with FileDb</b></font></p>
|
||||
<p><font face="Arial" size="3">Microsoft has done an amazing job with LINQ.
|
||||
They have invested a huge amount of time, effort and $
|
||||
in this technology which allows you to query just about
|
||||
any kind of data in a SQL-like way. We use LINQ
|
||||
with FileDb to join Tables as we would using SQL.
|
||||
The difference is that instead of doing it all in a
|
||||
single step with SQL, we must do it in two steps.
|
||||
First we select the data Tables from the database files
|
||||
then we use LINQ to join them together.</font></p>
|
||||
<p><font face="Arial" size="3">LINQ to Objects produces a list of anonymous types as
|
||||
its result set. This is good because we get
|
||||
strongly typed data objects which we can easily use in WPF/Silverlight apps.</font></p>
|
||||
<p><font face="Arial" size="3">Here is an example of doing a simple select using
|
||||
LINQ:</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" id="table36" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font face="Courier New" size="2">//
|
||||
Using the IN operator. Notice the ~
|
||||
prefix on the LastName field. This is how
|
||||
<br>
|
||||
// you can specify case insensitive searches<br>
|
||||
<br>
|
||||
Table
|
||||
employees = employeesDb.SelectRecords( "~LastName
|
||||
IN ('Fuller', 'Peacock')" );<br>
|
||||
<br>
|
||||
var query =
|
||||
from record in employees<br>
|
||||
select new<br>
|
||||
{<br>
|
||||
ID = record["EmployeeId"],<br>
|
||||
Name = record["FirstName"] + " " + record["LastName"],<br>
|
||||
Title = record["Title"]<br>
|
||||
};<br>
|
||||
<br>
|
||||
foreach( var rec in query )<br>
|
||||
{<br>
|
||||
Debug.WriteLine( rec.ToString() );<br>
|
||||
}</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
<p><font face="Arial" size="3">The only thing LINQ did for us in this example was
|
||||
gave us a typed list of anonymous objects. Here's
|
||||
the same thing but with custom objects:</font></p>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" id="table37" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font size="2">IList<Employee></font><font face="Courier New" size="2"> employees
|
||||
= employeesDb.SelectRecords<Employee>(
|
||||
"~LastName
|
||||
IN ('Fuller', 'Peacock')" );<br>
|
||||
<br>
|
||||
var query =<br>
|
||||
from e in employees<br>
|
||||
select e;<br>
|
||||
<br>
|
||||
foreach( var emp in query )<br>
|
||||
{<br>
|
||||
Debug.WriteLine( emp.ToString() );<br>
|
||||
}</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</blockquote>
|
||||
<p dir="ltr"><font face="Arial" size="3">Now lets tap into LINQ's real power to join tables together
|
||||
like a SQL inner join. Notice in the following example we use the </font>
|
||||
<font face="Courier New" size="2">FilterExpression.CreateInExpressionFromTable</font><font face="Arial"><font size="3">
|
||||
method. We do this to get only the records we are going to need with LINQ.
|
||||
So using FileDb with LINQ is a two step process. You first select the
|
||||
records you will need then use them in the LINQ query. If your database
|
||||
files are large, you can filter the records like this. Otherwise you can
|
||||
just select all records.</font></p>
|
||||
<blockquote>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" id="table38" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font face="Courier New" size="2">FileDb customersDb = new FileDb(),<br>
|
||||
ordersDb = new FileDb(),<br>
|
||||
orderDetailsDb = new FileDb(),<br>
|
||||
productsDb = new FileDb();<br>
|
||||
<br>
|
||||
customersDb.Open( "Customers.fdb" );<br>
|
||||
ordersDb.Open( "Orders.fdb" );<br>
|
||||
orderDetailsDb.Open( "OrderDetails.fdb" );<br>
|
||||
productsDb.Open( "Products.fdb" );<br>
|
||||
<br>
|
||||
// get our target Customer records<br>
|
||||
// Note that we should select only fields we
|
||||
need from each table, but to keep the code<br>
|
||||
// simple for this example we just pass in null for the field
|
||||
list<br>
|
||||
<br>
|
||||
FilterExpression filterExp =
|
||||
FilterExpression.Parse( "CustomerID IN( 'ALFKI',
|
||||
'BONAP' )" );<br>
|
||||
FileDbNs.Table customers =
|
||||
customersDb.SelectRecords( filterExp );<br>
|
||||
<br>
|
||||
// now get only Order records for the target
|
||||
Customer records<br>
|
||||
// CreateInExpressionFromTable will create
|
||||
an IN FilterExpression, which uses a HashSet
|
||||
<br>
|
||||
// for high efficiency when filtering
|
||||
records<br>
|
||||
<br>
|
||||
filterExp =
|
||||
FilterExpression.CreateInExpressionFromTable(
|
||||
"CustomerID", customers, "CustomerID" );<br>
|
||||
FileDbNs.Table orders =
|
||||
ordersDb.SelectRecords( filterExp );<br>
|
||||
<br>
|
||||
// now get only OrderDetails records for the
|
||||
target Order records<br>
|
||||
<br>
|
||||
filterExp =
|
||||
FilterExpression.CreateInExpressionFromTable(
|
||||
"OrderID", orders, "OrderID" );<br>
|
||||
FileDbNs.Table orderDetails =
|
||||
orderDetailsDb.SelectRecords( filterExp );<br>
|
||||
<br>
|
||||
// now get only Product records for the
|
||||
target OrderDetails records<br>
|
||||
<br>
|
||||
filterExp =
|
||||
FilterExpression.CreateInExpressionFromTable(
|
||||
"ProductID", orderDetails, "ProductID" );<br>
|
||||
FileDbNs.Table products =
|
||||
productsDb.SelectRecords( filterExp );<br>
|
||||
<br>
|
||||
// now we're ready to do the join<br>
|
||||
<br>
|
||||
var query =<br>
|
||||
from custRec in customers<br>
|
||||
join orderRec in orders on custRec["CustomerID"]
|
||||
equals orderRec["CustomerID"]<br>
|
||||
join orderDetailRec in orderDetails on
|
||||
orderRec["OrderID"] equals
|
||||
orderDetailRec["OrderID"]<br>
|
||||
join productRec in products on
|
||||
orderDetailRec["ProductID"] equals
|
||||
productRec["ProductID"]<br>
|
||||
select new<br>
|
||||
{<br>
|
||||
ID = custRec["CustomerID"],<br>
|
||||
CompanyName = custRec["CompanyName"],<br>
|
||||
OrderID = orderRec["OrderID"],<br>
|
||||
OrderDate = orderRec["OrderDate"],<br>
|
||||
ProductName = productRec["ProductName"],<br>
|
||||
UnitPrice = orderDetailRec["UnitPrice"],<br>
|
||||
Quantity = orderDetailRec["Quantity"]<br>
|
||||
};<br>
|
||||
<br>
|
||||
foreach( var rec in query )<br>
|
||||
{<br>
|
||||
Debug.WriteLine( rec.ToString() );<br>
|
||||
}</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
<p><font face="Arial" size="3">Here's the same thing again using custom objects:</font></p>
|
||||
<font FACE="Courier New">
|
||||
<table border="0" id="table39" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font face="Courier New" size="2">// get our target Customer records<br>
|
||||
<br>
|
||||
FilterExpression filterExp =
|
||||
FilterExpression.Parse( "CustomerID IN( 'ALFKI',
|
||||
'BONAP' )" );<br>
|
||||
IList<Customer> customers =
|
||||
customersDb.SelectRecords<Customer>( filterExp );<br>
|
||||
<br>
|
||||
filterExp =
|
||||
FilterExpression.CreateInExpressionFromTable<Customer>(
|
||||
"CustomerID", customers, "CustomerID" );<br>
|
||||
IList<Order> orders =
|
||||
ordersDb.SelectRecords<Order>( filterExp );<br>
|
||||
<br>
|
||||
// now get only OrderDetails records for the
|
||||
target Order records<br>
|
||||
<br>
|
||||
filterExp =
|
||||
FilterExpression.CreateInExpressionFromTable<Order>(
|
||||
"OrderID", orders, "OrderID" );<br>
|
||||
IList<OrderDetail> orderDetails =
|
||||
orderDetailsDb.SelectRecords<OrderDetail>( filterExp );<br>
|
||||
<br>
|
||||
// now get only Product records for the
|
||||
target OrderDetails records<br>
|
||||
<br>
|
||||
filterExp =
|
||||
FilterExpression.CreateInExpressionFromTable<OrderDetail>(
|
||||
"ProductID", orderDetails, "ProductID" );<br>
|
||||
IList<Product> products =
|
||||
productsDb.SelectRecords<Product>(( filterExp );<br>
|
||||
<br>
|
||||
// now we're ready to do the join<br>
|
||||
<br>
|
||||
var query =<br>
|
||||
from custRec in customers<br>
|
||||
join orderRec in orders on custRec.CustomerID
|
||||
equals orderRec.CustomerID<br>
|
||||
join orderDetailRec in orderDetails on
|
||||
orderRec.OrderID equals orderDetailRec.OrderID<br>
|
||||
join productRec in products on
|
||||
orderDetailRec.ProductID equals productRec.ProductID<br>
|
||||
select new<br>
|
||||
{<br>
|
||||
ID = custRec.CustomerID,<br>
|
||||
CompanyName = custRec.CompanyName,<br>
|
||||
OrderID = orderRec.OrderID,<br>
|
||||
OrderDate = orderRec.OrderDate,<br>
|
||||
ProductName = productRec.ProductName,<br>
|
||||
UnitPrice = orderDetailRec.UnitPrice,<br>
|
||||
Quantity = orderDetailRec.Quantity<br>
|
||||
};<br>
|
||||
<br>
|
||||
foreach( var rec in query )<br>
|
||||
{<br>
|
||||
Debug.WriteLine( rec.ToString() );<br>
|
||||
}</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p> </p>
|
||||
</font>
|
||||
<p><b>
|
||||
<font color="#0066CC" face="Arial" size="3">Creating a Database</font></p>
|
||||
</b>
|
||||
<p><font face="Arial" size="3">You create your database programmatically by defining
|
||||
Fields and adding them to an array then calling FileDb.Create, similar to below.
|
||||
Notice we set the ID field to be AutoIncrementing and PrimaryKey. This code
|
||||
creates a database with every type of field.</font></p>
|
||||
<font FACE="Courier New">
|
||||
<blockquote>
|
||||
<table border="0" width="100%" id="table40" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td><font size="2" FACE="Courier New">Field field;<br>
|
||||
var fieldLst = new List<Field>( 20 );<br>
|
||||
field = new Field( "ID", DataType.Int );<br>
|
||||
field.AutoIncStart = 0;<br>
|
||||
field.IsPrimaryKey = true;<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "FirstName", DataType.String );<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "LastName", DataType.String );<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "BirthDate", DataType.DateTime );<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "IsCitizen", DataType.Bool );<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "DoubleField", DataType.Double );<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "ByteField", DataType.Byte );<br>
|
||||
fields.Add( field );<br>
|
||||
<br>
|
||||
// array types<br>
|
||||
field = new Field( "StringArrayField", DataType.String );<br>
|
||||
field.IsArray = true;<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "ByteArrayField", DataType.Byte );<br>
|
||||
field.IsArray = true;<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "IntArrayField", DataType.Int );<br>
|
||||
field.IsArray = true;<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "DoubleArrayField", DataType.Double );<br>
|
||||
field.IsArray = true;<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "DateTimeArrayField", DataType.DateTime );<br>
|
||||
field.IsArray = true;<br>
|
||||
fields.Add( field );<br>
|
||||
field = new Field( "BoolArray", DataType.Bool );<br>
|
||||
field.IsArray = true;<br>
|
||||
fields.Add( field );</font><font size="2"><br>
|
||||
<br>
|
||||
var myDb = new FileDb();</font><font size="2" FACE="Courier New"><br>
|
||||
myDb.Create( "MyDatabase.fdb", fieldLst.ToArray() );</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
</font>
|
||||
<p><b><font color="#0066CC" face="Arial" size="3"><br>
|
||||
Adding Records</font></b></p>
|
||||
<p><font face="Arial" size="3">You add records to a database by creating a FieldValues
|
||||
object and adding field values. You do not need to represent every field of the
|
||||
database. Fields that are missing will be initialized to the default value (zero
|
||||
for numeric types, DateTime.MinValue,
|
||||
empty for String and NULL for array types).</font></p>
|
||||
<font FACE="Courier New">
|
||||
<blockquote>
|
||||
<table border="0" width="100%" id="table41" bgcolor="#FBEDBB" cellpadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<font size="2" FACE="Courier New">var record = new FieldValues();<br>
|
||||
record.Add( "FirstName", "Nancy" );<br>
|
||||
record.Add( "LastName", "Davolio" );<br>
|
||||
record.Add( "BirthDate", new DateTime( 1968, 12, 8 ) );<br>
|
||||
record.Add( "IsCitizen", true );<br>
|
||||
record.Add( "Double", 1.23 );<br>
|
||||
record.Add( "Byte", 1 );<br>
|
||||
record.Add( "StringArray", new string[] { "s1", "s2", "s3" } );<br>
|
||||
record.Add( "ByteArray", new Byte[] { 1, 2, 3, 4 } );<br>
|
||||
record.Add( "IntArray", new int[] { 100, 200, 300, 400 } );<br>
|
||||
record.Add( "DoubleArray", new double[] { 1.2, 2.4, 3.6, 4.8 } );<br>
|
||||
record.Add( "DateTimeArray", new DateTime[] { DateTime.Now, DateTime.Now,
|
||||
DateTime.Now, DateTime.Now } );<br>
|
||||
record.Add( "BoolArray", new bool[] { true, false, true, false } );<br>
|
||||
<br>
|
||||
myDb.AddRecord( record );</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p> </p>
|
||||
</font>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue