Skip to content

Commit

Permalink
Merge pull request #7 from VoltDB/doc_fixes
Browse files Browse the repository at this point in the history
Doc fixes
  • Loading branch information
rmorgenstein committed Mar 18, 2013
2 parents 967c75b + 7c45b75 commit 38138d0
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 12 deletions.
220 changes: 218 additions & 2 deletions README.txt
@@ -1,8 +1,224 @@
= VoltDB C# Client Library
VoltDB C# Client Library
========================

The VoltDB client library implements the native VoltDB wire
protocol. You can use the library to connect to a VoltDB cluster,
invoke stored procedures and read responses.

For an introduction to using the C# library:
http://blog.voltdb.com/introducing-voltdbnet-c-library-your-voltdb-applications/
[Introducting VoltDB.NET: C# Library for Your VoltDB Applications](http://blog.voltdb.com/introducing-voltdbnet-c-library-your-voltdb-applications/)

## Getting Started ##

Download the driver:
- Latest build with documentation: [Downloads](http://voltdb.com/tao-volt/downloads-home.php)
- Full source on Github: [voltdb-client-csharp](https://github.com/VoltDB/voltdb-client-csharp)

## VoltDB.NET in a nutshell ##

The .NET/C# client library for VoltDB is extremely flexible and allows you to develop WinForms, Console and Web applications and services much as you would leveraging any other back-end data service or database.

- Connect with a customized connectionstring in your app/web.config.
- Perform Synchronous or Asynchronous data operations using standard .NET design patterns.
- Consume and filter data results using LINQ.
- Leverage native, strongly-typed, data access and type casting, as well as late-bound operations.
- Monitor performance and manage a database cluster.

Key considerations:

- All access is thread-safe
- Safe for multi-threaded application
- Safe as shared connections for a website/service
- OK to mix asynchronous and synchronous calls
- OK to have long-running callbacks (they are Thread-Pooled)
- Resilience
- Connect to multiple nodes
- Performance
- Share: multi-threading on a single connection is faster
- Production: No Tracing (ever) or Statistics (unless needed)
- Avoid usage of IAsync WaitHandles: they are slow!


## Connecting to VoltDB ##

Read the blog post: [VoltDB.NET: Optimizing your Connection Settiongs](http://blog.voltdb.com/blog-net-optimizing/). Note the following in particular:
- Use Cluster connections: this will provide a more resilient connection and will automatically reconnect if a connection to one of the servers in a cluster is lost.
- Use Connectionstrings: this allows for more flexibility in defining which servers to connect to.

Key Connection Options:
- Port – default: 21212
- MaxOutstandingTransaction (txnq) – default: 3,000
- Statistics (stats) – default: false
- CommandTimeout – default: 5,000(ms)
- AllowSystemCalls (system) – default: false
- AllowAdHocQueries (adhoc) – default: false

## Synchronous and Asynchronous Calls ##

Another blog post, [VoltDB.NET: Synchronous vs. Asynchronous Request Processing](http://blog.voltdb.com/blog-voltdb-net/) covers the benefits of using asynchronous requests, and how this impacts .NET application development.

Synchronous = Do nothing until you get the answer
- Good: ‘Procedural’ model easier to understand/work with
- Bad: Limits your throughput
- Redeeming: For this thread only

Asynchronous = Call me when you get the answer
- Good: No bottlenecks on wait operations
- Bad: ‘Disjointed’ model harder to work with/error prone
- Redeeming: Known ‘Best Practice’ patterns

VoltDB.NET implements:
- Sync: .Execute
- Async: .Begin/.Cancel/.End with IAsyncResult

# Example Code #

## Calling Procedures ##

Define Callback for Asynchronous call

void MyDelegate(Response<Table[]> response) {
if (response.Status == ResponseStatus.Success) {
… // Send response to client, update UI, etc.
}
else {
… // Deal with error
}
}

Create Strongly-typed Wrappers

var my = conn.Procedures.Wrap<Table[],int,string>("MyProcedure", MyDelegate);

Supported Data Types:

* Result:
- Table[], Table
- SingleRowTable[], SingleRowTable
- int[], long[], string[], double[], … (and nullable types)
- int, long, … (and nullable types)
* Parameters:
- int[], long[], string[], double[], …
- int, long, …

Execute the procedure

Response<Table[]> r = myProc.Execute(1, “test”);

IAsyncResult h = my.BeginExecute(1, “test”);
IAsyncResult h = my.BeginExecute(1, “test”, state);

Cancel Async Execution

myProc.ExecuteCancelAsync(h);

Get Async results (if not using callback)

Response<Table[]> r = myProc.EndExecute(h);

Wrapper Rules:

- Up to 35 input parameters
- Types must be compatible with core VoltDB types
- Types can be single-values or arrays
- sbyte, short, int, long, double, VoltDecimal, DateTime, string
- sbyte?, short?, int?, …
- sbyte[], sbyte?[], short[], short?[], …


Another option is to use Runtime Wrappers, but the type of runtime values must still be compatible.

conn.Procedures.Wrap<Table[],object,…,object>(…);

Per-execution callback delegate/closures

IAsyncResult h = my.BeginExecute(1, "test", MyDelegate);

// or...

h = my.BeginExecute( 1, "test", (r) => MyClosureFunction(r, …) );

Re-use Wrappers across connections (of course, executions still occur in the initiating context/connection).

my.SetConnection(otherVoltConnection);



## Consuming Results ##

Access data directly...

double? value = response.Result
.GetValue<double?>(col, row);

double? Value = response.Result
.Rows
.ElementAt(row)
.GetValue<double?>(col);

...or through Strongly-typed Table Wrappers

var myTable = response.Result.Wrap<int?,…,double?>();

double? value = myTable.Column7[row];

Wrapper Rules:

- Up to 35 columns
- Types must be compatible with core VoltDB types and flagged as Nullable => use int? (not int)
- sbyte?, short?, int?, long?, double?, VoltDecimal?, DateTime? and string

Results are LINQ-friendly:

// On a strongly-typed VoltDB data table
myTable.Rows.Where(r => r.Column2 == "Books")
.Select(r => new { Title = r.Column2, Price = r.Column7 })
.OrderBy(p => p.Price);

// On a raw VoltDB data table
raw.Rows.Where(r => r.GetValue<string>(1) == "Books")
.Select(r => new { Title = r. GetValue<string>(1), Price = r. GetValue<double>(6) })
.OrderBy(p => p.Price);

Access metadata:

int count = myTable.RowCount;
bool check = myTable.HasData;

string name = raw.GetColumnName(idx);
short idx = raw.GetColumnIndex(name);

Type type = raw.GetColumnType(idx);
DBType type = raw.GetColumnDBType(idx);

int?[] column1Data = raw.GetColumnData<int?>(0);
object[] column1Data = raw.GetColumnData(0);

Fill a (System.Data.)DataTable

Table raw = procedureWrapper.Execute().Result;
DataTable dt = new DataTable("Result");
for(short i = 0; i < raw.ColumnCount; i++)
dt.Columns.Add( raw.GetColumnName(i), raw.GetColumnType(i));
object[] values = new object[raw.ColumnCount];
foreach (Row row in raw.Rows) {
for (short i = 0; i < raw.ColumnCount; i++)
values[i] = row.GetValue(i);
dt.Rows.Add(values);
}

Fill a (System.Windows.Forms.)DataGridView

view.Columns.Clear();
view.DataSource = null;
for (short i = 0; i &lt; raw.ColumnCount; i++)
view.Columns.Add(raw.GetColumnName(i), raw.GetColumnName(i));
foreach (Row row in raw.Rows) {
int n = view.Rows.Add();
for (short i = 0; i < row.ColumnCount; i++) {
view.Rows[n].Cells[i].Value = row.GetValue(i);
view.Rows[n].Cells[i].ValueType = row.GetColumnType(i);
}
}


5 changes: 2 additions & 3 deletions VoltDB.Data.Client/Connections/ProcedureAccess.cs
Expand Up @@ -48,13 +48,12 @@ internal ProcedureAccess(VoltConnection executor)
}

/// <summary>
/// Regular expression used to validate tokens (procedure names only for now) (will make sure the name doesn't
/// have any @ sign, or other invalid character for that matter).
/// Regular expression used to validate tokens
/// </summary>
private Regex TokenValidator = new Regex("^[a-zA-Z0-9_.$@]*$");

/// <summary>
/// Validate the procedure name (alpahnumeric only, no @)
/// Validate the procedure name
/// </summary>
/// <param name="procedureName">Name of the procedure</param>
private void ValidateProcedureName(string procedureName)
Expand Down
14 changes: 7 additions & 7 deletions build.documentation.txt
Expand Up @@ -2,8 +2,8 @@ Building the C# Client Library & Kits


Software Requirements
- Visual Studio 2008 or 2010 C# Express Edition
http://www.microsoft.com/express/Downloads/
- Visual Studio 2008, 2010, or 2012 C# Express Edition
http://www.microsoft.com/visualstudio/eng/products/visual-studio-express-products

- Sandcastle Help File Builder
http://shfb.codeplex.com/releases/
Expand All @@ -14,18 +14,18 @@ Software Requirements
+ "MAML Schema IntelliSense" -> skip
+ "Sandcastle Help File Builder" -> install SHFB

- Tortoise SVN
http://tortoisesvn.net/downloads.html
+ needed to grab source code from SVN in Windows
- Github:Windows
http://windows.github.com/
+ needed to clone source code from Github in Windows

- 7z Compressor
http://www.7-zip.org/download.html


Building the Client Library

1. SVN Checkout:
svn://clientapi/csharp/trunk
1. Github Clone:
https://github.com/VoltDB/voltdb-client-csharp

2. Build Assemblies (Visual Studio)
Open ./VoltDB.ClientLibrary.VS2010.sln
Expand Down

0 comments on commit 38138d0

Please sign in to comment.