Net4x.Data.DataSetExtensions
4.8.0.26251
dotnet add package Net4x.Data.DataSetExtensions --version 4.8.0.26251
NuGet\Install-Package Net4x.Data.DataSetExtensions -Version 4.8.0.26251
<PackageReference Include="Net4x.Data.DataSetExtensions" Version="4.8.0.26251" />
<PackageVersion Include="Net4x.Data.DataSetExtensions" Version="4.8.0.26251" />
<PackageReference Include="Net4x.Data.DataSetExtensions" />
paket add Net4x.Data.DataSetExtensions --version 4.8.0.26251
#r "nuget: Net4x.Data.DataSetExtensions, 4.8.0.26251"
#:package Net4x.Data.DataSetExtensions@4.8.0.26251
#addin nuget:?package=Net4x.Data.DataSetExtensions&version=4.8.0.26251
#tool nuget:?package=Net4x.Data.DataSetExtensions&version=4.8.0.26251
Net4x.Data.DataSetExtensions
LINQ to DataSet for .NET Framework 3.5 and 4.0.
System.Data.DataSetExtensions.dll — the assembly that gives you AsEnumerable(), Field<T>(),
CopyToDataTable() and the DataRowComparer — only ships with .NET Framework 3.5 SP1 and later, and
the types are not available at all in some trimmed or repackaged runtimes. This package provides a
drop-in implementation of that API surface under the original System.Data namespace, so code
written against LINQ to DataSet compiles and runs unchanged on the older frameworks.
Target frameworks
| Target framework | What you get |
|---|---|
net35, net40 |
The full implementation, compiled into this assembly. |
net45, netstandard2.0 |
A thin facade that takes a dependency on the official System.Data.DataSetExtensions package, so the framework types are used instead. |
Because the types live in the System.Data namespace, multi-targeted projects reference this package
once and get the right implementation for every target framework, with no #if in your own code.
Installation
dotnet add package Net4x.Data.DataSetExtensions
or, from the Package Manager Console:
Install-Package Net4x.Data.DataSetExtensions
Usage
Everything lives in System.Data, so an existing using System.Data; is all you need.
Querying a DataTable
using System.Data;
using System.Linq;
DataTable scores = GetScores();
var winners = scores.AsEnumerable()
.Where(row => row.Field<int>("Score") >= 80)
.OrderByDescending(row => row.Field<int>("Score"))
.ThenBy(row => row.Field<string>("Name"))
.Select(row => new { Name = row.Field<string>("Name"), Score = row.Field<int>("Score") });
Query syntax works as well:
var winners = from row in scores.AsEnumerable()
where row.Field<int>("Score") >= 80
orderby row.Field<int>("Score") descending
select row.Field<string>("Name");
Typed field access
Field<T> unwraps DBNull for you: nullable and reference types come back as null, while a
non-nullable value type throws InvalidCastException rather than returning a surprise.
string name = row.Field<string>("Name"); // null when the column is DBNull
int? bonus = row.Field<int?>("Bonus"); // null when the column is DBNull
int score = row.Field<int>("Score"); // InvalidCastException when the column is DBNull
// by index, by DataColumn, and per row version
int original = row.Field<int>("Score", DataRowVersion.Original);
int byIndex = row.Field<int>(3);
int byColumn = row.Field<int>(scores.Columns["Score"]);
SetField<T> is the mirror image and translates null into DBNull.Value:
row.SetField("Name", "Dorkpuff");
row.SetField<int?>("Bonus", null); // stores DBNull.Value
Materialising a query back into a DataTable
DataTable winnersTable = scores.AsEnumerable()
.Where(row => row.Field<int>("Score") >= 80)
.CopyToDataTable();
// or load into a table you already own
scores.AsEnumerable().CopyToDataTable(existingTable, LoadOption.Upsert);
// with per row error handling
scores.AsEnumerable().CopyToDataTable(existingTable, LoadOption.Upsert, (sender, e) =>
{
Log(e.Errors);
e.Continue = true; // skip the offending row and keep going
});
CopyToDataTable without a target table clones the source schema. An empty sequence throws
InvalidOperationException in that case, because there is no schema to infer.
Comparing rows by value
var distinct = scores.AsEnumerable().Distinct(DataRowComparer.Default);
bool same = DataRowComparer.Default.Equals(rowA, rowB);
DataRowComparer compares column values rather than references, and understands one dimensional
arrays: two rows holding equal byte[] contents compare equal.
Typed DataSets
Designer generated typed DataSets derive their tables from TypedTableBase<TRow>, which this package
provides along with its extension methods:
ScoreTable table = dataSet.Score;
ScoreRow first = table.ElementAtOrDefault(0); // null instead of throwing
var top = table.Where(r => r.Score >= 80)
.OrderByDescending(r => r.Score);
API surface
DataTableExtensions—AsEnumerable,CopyToDataTable(3 overloads)DataRowExtensions—Field<T>(6 overloads),SetField<T>(3 overloads)DataRowComparer,DataRowComparer<TRow>EnumerableRowCollection,EnumerableRowCollection<TRow>,OrderedEnumerableRowCollection<TRow>EnumerableRowCollectionExtensions—Cast,Where,Select,OrderBy,OrderByDescending,ThenBy,ThenByDescending(each with and without anIComparer<TKey>)TypedTableBase<T>,TypedTableBaseExtensions
Known limitation
DataTableExtensions.AsDataView and EnumerableRowCollection<T>.AsDataView are not implemented on
net35 and net40. Everything else in the LINQ to DataSet surface is. Consumers that need a live,
bindable DataView over a query result should sort and filter through DataView directly.
Building from source
The library multi-targets net35;net40;net45;netstandard2.0. Building the net35 target requires the
full Visual Studio MSBuild, because the .NET SDK's dotnet build cannot run the CLR2 resource
generator; the other target frameworks build with dotnet build.
Licence
Copyright © Piero Viano. The assembly is strong named.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. 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 was computed. 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 was computed. 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 was computed. 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 | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net35 is compatible. net40 is compatible. net403 was computed. net45 is compatible. net451 was computed. net452 was computed. net46 was computed. 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. |
-
.NETFramework 3.5
- Net4x.AsyncBridge (>= 1.5.0.26250)
-
.NETFramework 4.0
- Net4x.AsyncBridge (>= 1.5.0.26250)
-
.NETFramework 4.5
- Net4x.AsyncBridge (>= 1.5.0.26250)
- System.Data.DataSetExtensions (>= 4.5.0)
-
.NETStandard 2.0
- Net4x.AsyncBridge (>= 1.5.0.26250)
- System.Data.DataSetExtensions (>= 4.5.0)
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 |
|---|---|---|
| 4.8.0.26251 | 63 | 9/10/2026 |
| 4.7.0 | 326 | 4/4/2025 |