Chiola.AseClient.StrongName 0.20.1

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Chiola.AseClient.StrongName --version 0.20.1
                    
NuGet\Install-Package Chiola.AseClient.StrongName -Version 0.20.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Chiola.AseClient.StrongName" Version="0.20.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Chiola.AseClient.StrongName" Version="0.20.1" />
                    
Directory.Packages.props
<PackageReference Include="Chiola.AseClient.StrongName" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Chiola.AseClient.StrongName --version 0.20.1
                    
#r "nuget: Chiola.AseClient.StrongName, 0.20.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Chiola.AseClient.StrongName@0.20.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Chiola.AseClient.StrongName&version=0.20.1
                    
Install as a Cake Addin
#tool nuget:?package=Chiola.AseClient.StrongName&version=0.20.1
                    
Install as a Cake Tool

Chiola.AseClient

This is a fork of DataAction/AdoNetCore.AseClient, a .NET data provider for SAP/Sybase ASE originally created and maintained by DataAction and its contributors. All credit for the original TDS protocol implementation goes to them — see LICENSE (Apache-2.0, preserved from upstream).

Why this fork exists: built as the driver dependency for Chiola.EntityFrameworkCore.Ase, a from-scratch EF Core provider for SAP ASE. Several real bugs and gaps in the upstream driver were found and worked around while building that provider (see its DECISIONS.md) — this fork exists to fix them directly at the source instead of accumulating workarounds downstream.

What changed from upstream (see DECISIONS.md for the full history and reasoning behind each of these):

  • Targets net5.0net9.0 in addition to upstream's full legacy matrix (netcoreapp1.0 through netstandard2.0/net46). The fork briefly dropped everything but net9.0 (its only consumer at the time), then restored the original matrix so this package can benefit anyone still on an older target, not just this fork's own use case — net5.0net9.0 were added on top, not swapped in, closing the gap between upstream's newest target (2019) and modern .NET.
  • Dropped the AdoNetCore.AseClient.Benchmark project (outdated BenchmarkDotNet 0.10.14, not relevant to this fork's goal) — AdoNetCore.AseClient.StrongName was kept (restored alongside the target matrix).
  • Test project pinned to NUnit 3.x (upstream's actual test suite, ~1200 unit tests + a real integration suite against live ASE) rather than upgrading to NUnit 4 outright, to avoid churn from its CollectionAssert/StringAssert namespace move — revisit later if worth it. The test project itself only runs against net9.0 today (not the full matrix like src/) — see CLAUDE.md.
  • Real bug fixes (see DECISIONS.md for each): AseConnection.ClearPool()/ClearPools() were literal no-ops upstream (//todo: implement) — implemented for real via a pool-generation pattern. Added proactive idle-connection eviction to the pool (previously only checked lazily, when a connection was next reserved — a pool that went idle just stayed open on the server forever).

Package published as Chiola.AseClient / Chiola.AseClient.StrongName on NuGet (not AdoNetCore.AseClient, to avoid clashing with the upstream package).

A .NET data provider for SAP ASE — fork of DataAction/AdoNetCore.AseClient.

SAP (formerly Sybase) has supported accessing the ASE database management system from ADO.NET for many years. Unfortunately SAP has not yet made a driver available to support .NET Core, so this project enables product teams that are dependent upon ASE to keep moving their application stack forwards.

The current .NET 4 version of SAP's Sybase.Data.AseClient driver is a .NET Framework managed wrapper around SAP's unmanged ADO DB provider and is dependent upon COM. COM is a Windows-only technology and will never be available to .NET Core, making it difficult to port the existing SAP driver.

Under the hood, ASE (and Microsoft Sql Server for that matter) relies on an application-layer protocol called Tabular Data Stream to transfer data between the database server and the client application. ASE uses TDS 5.0.

This project provides a .NET Core native implementation of the TDS 5.0 protocol via an ADO.NET DB Provider, making SAP ASE accessible from .NET Core applications hosted on Windows, Linux, Docker and also serverless platforms like AWS Lambda.

Table of Contents

Downloads

The latest stable release of the AdoNetCore.AseClient is available on NuGet.

Objectives

  • Functional parity with the Sybase.Data.AseClient provided by SAP. Ideally, our driver will be a drop in replacement for the Sybase.Data.AseClient (with some namespace changes). The following types are supported:

    • AseClientFactory - .NET Core 2.1+
    • AseCommand
    • AseCommandBuilder
    • AseConnection
    • AseConnectionPool
    • AseConnectionPoolManager
    • AseDataAdapter
    • AseDataReader
    • AseDbType
    • AseDecimal
    • AseError
    • AseErrorCollection
    • AseException
    • AseInfoMessageEventArgs
    • AseInfoMessageEventHandler
    • AseParameter
    • AseParameterCollection
    • AseRowUpdatedEventArgs - .NET Core 2.0+
    • AseRowUpdatedEventHandler - .NET Core 2.0+
    • AseRowUpdatingEventArgs - .NET Core 2.0+
    • AseRowUpdatingEventHandler - .NET Core 2.0+
    • TraceEnterEventHandler
    • TraceExitEventHandler
  • Not all features are currently supported, and some features will not be supported. Refer to upstream's Unsupported features wiki page (still applicable — this fork hasn't diverged on feature support yet).

  • Performance equivalent to or better than that of Sybase.Data.AseClient provided by SAP. This is possible as we are eliminating the COM and OLE DB layers from this driver and .NET Core is fast.

  • Target all of upstream's frameworks (netcoreapp1.0 through netstandard2.0/net46) plus net5.0net9.0.

  • Should work with Dapper at least as well as the Sybase.Data.AseClient

Performance benchmarks

The benchmark project (AdoNetCore.AseClient.Benchmark) and its historical results against Sybase.Data.AseClient were dropped in this fork (see the fork notice above) — not relevant to this fork's goal of serving Chiola.EntityFrameworkCore.Ase. See upstream's README for the original methodology and results.

Connection strings

connectionstrings.com lists the following connection string properties for the ASE ADO.NET Data Provider. In keeping with our objective of being a drop-in replacement for the Sybase.Data.AseClient, we aim to use identical connection string syntax to the Sybase.Data.AseClient, however our support for the various properties will be limited. Our support is as follows:

Property Support Notes
AnsiNull By default (0) AnsiNull is disabled which means that SQL statements can use = NULL and IS NULL syntax. Set to 1 to instruct the connection to only permit IS NULL syntax.
ApplicationName or Application Name
BufferCacheSize Buffer caching is automatically managed via an internal ArrayPool<T>. Setting this value in the connection string does nothing, but the behaviour is supported.
Charset If not specified, the server should dictate the character set
ClientHostName
ClientHostProc
CodePageType This doesn't appear to be relevant any more. You can specify the Charset without reference to a code page type, or allow the server to set the Charset which is the default behaviour.
Connection Lifetime or ConnectionLifetime
ConnectionIdleTimeout or Connection IdleTimeout or Connection Idle Timeout
CumulativeRecordCount TODO
Database or Db or Initial Catalog
Data Source or DataSource or Address or Addr or Network Address or Server Name
DSURL or Directory Service URL Multiple URLs are not supported; network drivers other than NLWNSCK (TCP/IP socket) are not supported; LDAP is not supported
EnableServerPacketSize
Encryption The designated encryption. Possible values: ssl, none.
EncryptPassword Values 0 (disabled) and 1 (enabled) are supported. The highest encryption standard of the ASE 15.x and 16x servers is implemented.
LoginTimeOut or Connect Timeout or Connection Timeout For pooled connections this translates to the time it takes to reserve a connection from the pool
Max Pool Size
Min Pool Size <ul><li>The pool will attempt to prime itself on creation up to this size (in a thread)</li><li>When a connection is killed, the pool will attempt to replace it if the pool size is less than Min</li></ul>
NamedParameters
PacketSize or Packet Size The server can decide to change this value
Ping Server
Pooling
Port or Server Port
Pwd or Password
TextSize
TrustedFile This property must be used along with Encryption=ssl. The value must be set to the path to the trusted file.
Uid or UserID or User ID or User
UseAseDecimal

Supported types

Types supported when sending requests to the database

DbType Send .NET Type(s) Notes
AnsiString string
AnsiStringFixedLength string
Binary byte[]
Boolean bool
Byte byte
Currency decimal Sent as decimal type; may change to send as TDS_MONEY, which is shorter
Date DateTime Time component is ignored
DateTime DateTime
DateTime2 X ASE does not support a DateTime2 type. Use DateTime instead
DateTimeOffset X ASE does not support a DateTimeOffset type. Use DateTime instead
Decimal decimal
Double double
Guid System.Guid Technically ASE does not support GUID or UUID types. Our driver supports it, but converts to Binary under the hood. You can obtain the same result by calling .ToByteArray() and using DbType.Binary.
Int16 short
Int32 int
Int64 long
Object X ASE does not support an Object type
SByte sbyte Sent as int16
Single float
String string UTF-16 encoded, sent to server as binary with usertype 35
StringFixedLength string UTF-16 encoded, sent to server as binary with usertype 34
Time TimeSpan
UInt16 ushort
UInt32 uint
UInt64 ulong
VarNumeric decimal
Xml X ASE does not support an Xml type

Types supported when reading responses from the database

ASE Type Receive .NET Type(s) Notes
bigdatetime X DateTime To be implemented. TDS_BIGDATETIME = 0xBB
bigint long
bigtime X DateTime To be implemented. TDS_BIGTIME = 0xBC
binary byte[]
bit bool
char string
date DateTime
datetime DateTime
decimal decimal
double precision double
float float
image byte[]
int int
money decimal
nchar string
numeric decimal
nvarchar string
smalldatetime DateTime
smallint short
smallmoney decimal
time DateTime We have added a GetTimeSpan method to AseDataReader
tinyint byte
unichar string Server sends as binary with usertype 34
univarchar string Server sends as binary with usertype 35
unsigned bigint ulong
unsigned int uint
unsigned smallint usmallint
varchar string
text string
unitext string
varbinary byte[]

Code samples

Open a database connection

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using(var connection = new AseConnection(connectionString))
{
    connection.Open();

    // use the connection...
}

Execute a SQL statement and read response data

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString))
{
    connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = "SELECT FirstName, LastName FROM Customer";

        using (var reader = command.ExecuteReader())
        {
            // Get the results.
            while (reader.Read())
            {
                var firstName = reader.GetString(0);
                var lastName = reader.GetString(1);

                // Do something with the data...
            }
        }
    }
}

Execute a SQL statement that returns no results

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString))
{
    connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = "INSERT INTO Customer (FirstName, LastName) VALUES ('Fred', 'Flintstone')";

        var recordsModified = command.ExecuteNonQuery();
    }
}

Execute a SQL statement that returns a scalar value

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString))
{
    connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = "SELECT COUNT(*) FROM Customer";

        var result = command.ExecuteScalar();
    }
}

Use input parameters with a SQL query

Note: ASE only allows Output, InputOutput, and ReturnValue parameters with stored procedures

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString)
{
    connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = "SELECT TOP 1 FirstName FROM Customer WHERE LastName = @lastName";

        command.Parameters.AddWithValue("@lastName", "Rubble");

        var result = command.ExecuteScalar();
    }
}

Execute a stored procedure and read response data

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString)
{
    connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = "GetCustomer";
        command.CommandType = CommandType.StoredProcedure;

        command.Parameters.AddWithValue("@lastName", "Rubble");

        using (var reader = command.ExecuteReader())
        {
            // Get the results.
            while (reader.Read())
            {
                var firstName = reader.GetString(0);
                var lastName = reader.GetString(1);

                // Do something with the data...
            }
        }
    }
}

Execute a stored procedure that returns no results

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString))
{
    connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = "CreateCustomer";
        command.CommandType = CommandType.StoredProcedure;

        command.Parameters.AddWithValue("@firstName", "Fred");
        command.Parameters.AddWithValue("@lastName", "Flintstone");

        command.ExecuteNonQuery();
    }
}

Execute a stored procedure that returns a scalar value

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString))
{
    connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = "CountCustomer";
        command.CommandType = CommandType.StoredProcedure;

        var result = command.ExecuteScalar();
    }
}

Use input, output, and return parameters with a stored procedure

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString))
{
    connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = "GetCustomerFirstName";
        command.CommandType = CommandType.StoredProcedure;

        command.Parameters.AddWithValue("@lastName", "Rubble");

        var outputParameter = command.Parameters.Add("@firstName", AseDbType.VarChar);
        outputParameter.Direction = ParameterDirection.Output;

        var returnParameter = command.Parameters.Add("@returnValue", AseDbType.Integer);
        returnParameter.Direction = ParameterDirection.ReturnValue;

        command.ExecuteNonQuery();

        //Do something with outputParameter.Value and returnParameter.Value...
    }
}

Execute a stored procedure and read response data with Dapper

var connectionString = "Data Source=myASEserver;Port=5000;Database=myDataBase;Uid=myUsername;Pwd=myPassword;";

using (var connection = new AseConnection(connectionString))
{
    connection.Open();

    var barneyRubble = connection.Query<Customer>("GetCustomer", new {lastName = "Rubble"}, commandType: CommandType.StoredProcedure).First();

    // Do something with the result...
}
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp1.0 is compatible.  netcoreapp1.1 is compatible.  netcoreapp2.0 is compatible.  netcoreapp2.1 is compatible.  netcoreapp2.2 is compatible.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net46 is compatible.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated

Fork of DataAction/AdoNetCore.AseClient — see README.md and DECISIONS.md for what changed.