linq2db 4.3.0
Prefix ReservedSee the version list below for details.
dotnet add package linq2db --version 4.3.0
NuGet\Install-Package linq2db -Version 4.3.0
<PackageReference Include="linq2db" Version="4.3.0" />
paket add linq2db --version 4.3.0
#r "nuget: linq2db, 4.3.0"
// Install linq2db as a Cake Addin #addin nuget:?package=linq2db&version=4.3.0 // Install linq2db as a Cake Tool #tool nuget:?package=linq2db&version=4.3.0
LINQ to DB
LINQ to DB is the fastest LINQ database access library offering a simple, light, fast, and type-safe layer between your POCO objects and your database.
Architecturally it is one step above micro-ORMs like Dapper, Massive, or PetaPoco, in that you work with LINQ expressions, not with magic strings, while maintaining a thin abstraction layer between your code and the database. Your queries are checked by the C# compiler and allow for easy refactoring.
However, it's not as heavy as LINQ to SQL or Entity Framework. There is no change-tracking, so you have to manage that yourself, but on the positive side you get more control and faster access to your data.
In other words LINQ to DB is type-safe SQL.
Standout Features
- Rich Querying API:
- Explicit Join Syntax (In addition to standard LINQ join syntax)
- CTE Support
- Bulk Copy/Insert
- Window/Analytic Functions
- Merge API
- Extensibility:
Visit our blog and see Github.io documentation for more details.
Code examples and demos can be found here or in tests.
Related linq2db and 3rd-party projects
- linq2db.EntityFrameworkCore (adds support for linq2db functionality in EF.Core projects)
- LINQPad Driver
- DB2 iSeries Provider
- ASP.NET CORE 2 Template
- ASP.NET CORE 3 Template with Angular
- ASP.NET CORE 5 Template
- PostGIS extensions for linq2db
Notable open-source users:
- nopCommerce - popular open-source e-commerce solution
- OdataToEntity - library to create OData service from database context
- SunEngine - site, blog and forum engine
Configuring connection strings
Passing Into Constructor
You can simply pass provider name and connection string into DataConnection
constructor:
var db = new LinqToDB.Data.DataConnection(
LinqToDB.ProviderName.SqlServer2012,
"Server=.\;Database=Northwind;Trusted_Connection=True;Enlist=False;");
Using Connection Options Builder
You can configure connection options from code using LinqToDBConnectionOptionsBuilder
class (check class for available options):
// create options builder
var builder = new LinqToDBConnectionOptionsBuilder();
// configure connection string
builder.UseSqlServer(connectionString);
// or using custom connection factory
b.UseConnectionFactory(
SqlServerTools.GetDataProvider(
SqlServerVersion.v2017,
SqlServerProvider.MicrosoftDataSqlClient),
() =>
{
var cn = new SqlConnection(connectionString);
cn.AccessToken = accessToken;
return cn;
});
// pass configured options to data connection constructor
var dc = new DataConnection(builder.Build());
Using Config File (.NET Framework)
In your web.config
or app.config
make sure you have a connection string (check this file for supported providers):
<connectionStrings>
<add name="Northwind"
connectionString = "Server=.\;Database=Northwind;Trusted_Connection=True;Enlist=False;"
providerName = "SqlServer" />
</connectionStrings>
Using Connection String Settings Provider
Alternatively, you can implement custom settings provider with ILinqToDBSettings
interface, for example:
public class ConnectionStringSettings : IConnectionStringSettings
{
public string ConnectionString { get; set; }
public string Name { get; set; }
public string ProviderName { get; set; }
public bool IsGlobal => false;
}
public class MySettings : ILinqToDBSettings
{
public IEnumerable<IDataProviderSettings> DataProviders
=> Enumerable.Empty<IDataProviderSettings>();
public string DefaultConfiguration => "SqlServer";
public string DefaultDataProvider => "SqlServer";
public IEnumerable<IConnectionStringSettings> ConnectionStrings
{
get
{
yield return
new ConnectionStringSettings
{
Name = "Northwind",
ProviderName = ProviderName.SqlServer,
ConnectionString =
@"Server=.\;Database=Northwind;Trusted_Connection=True;Enlist=False;"
};
}
}
}
And later just set on program startup before the first query is done (Startup.cs for example):
DataConnection.DefaultSettings = new MySettings();
Define POCO class
You can generate POCO classes from your database using T4 templates. These classes will be generated using the Attribute configuration
. Demonstration video could be found here.
Alternatively, you can write them manually, using Attribute configuration
, Fluent configuration
, or inferring.
Attribute configuration
using System;
using LinqToDB.Mapping;
[Table("Products")]
public class Product
{
[PrimaryKey, Identity]
public int ProductID { get; set; }
[Column("ProductName"), NotNull]
public string Name { get; set; }
[Column]
public int VendorID { get; set; }
[Association(ThisKey = nameof(VendorID), OtherKey = nameof(Vendor.ID))]
public Vendor Vendor { get; set; }
// ... other columns ...
}
This approach involves attributes on all properties that should be mapped. This way lets you to configure all possible things linq2db ever supports. There one thing to mention: if you add at least one attribute into POCO, all other properties should also have attributes, otherwise they will be ignored:
using System;
using LinqToDB.Mapping;
[Table("Products")]
public class Product
{
[PrimaryKey, Identity]
public int ProductID { get; set; }
// Property `Name` will be ignored as it lacks `Column` attibute.
public string Name { get; set; }
}
Fluent Configuration
This method lets you configure your mapping dynamically at runtime. Furthermore, it lets you to have several different configurations if you need so. You will get all configuration abilities available with attribute configuration. These two approaches are interchangeable in its abilities. This kind of configuration is done through the class MappingSchema
.
With fluent approach you can configure only things that require it explicitly. All other properties will be inferred by linq2db:
// IMPORTANT: configure mapping schema instance only once
// and use it with all your connections that need those mappings
// Never create new mapping schema for each connection as
// it will seriously harm performance
var mappingSchema = new MappingSchema();
var builder = mappingSchema.GetFluentMappingBuilder();
builder.Entity<Product>()
.HasTableName("Products")
.HasSchemaName("dbo")
.HasIdentity(x => x.ProductID)
.HasPrimaryKey(x => x.ProductID)
.Ignore(x => x.SomeNonDbProperty)
.Property(x => x.TimeStamp)
.HasSkipOnInsert()
.HasSkipOnUpdate()
.Association(x => x.Vendor, x => x.VendorID, x => x.VendorID, canBeNull: false)
;
//... other mapping configurations
In this example we configured only three properties and one association. We let linq2db to infer all other properties which have to match with column names. However, other associations will not get configured automatically.
There is a static property LinqToDB.Mapping.MappingSchema.Default
which may be used to define a global configuration. This mapping is used by default if no mapping schema provided explicitly. The other way is to pass instance of MappingSchema
into constructor alongside with connection string.
Inferred Configuration
This approach involves no attributes at all. In this case linq2db will use POCO's name as table name and property names as column names (with exact same casing, which could be important for case-sensitive databases). This might seem to be convenient, but there are some restrictions: linq2db will not infer primary key even if class has property called ID
; it will not infer nullability of string properties as there is no way to do so; and associations will not be automatically configured.
using System;
using LinqToDB.Mapping;
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public int VendorID { get; set; }
public Vendor Vendor { get; set; }
// ... other columns ...
}
This way linq2db will auto-configure Product
class to map to Product
table with fields ProductID
, Name
, and VendorID
. POCO will not get ProductID
property treated as primary key. And there will be no association with Vendor
.
This approach is not generally recommended.
DataConnection class
At this point LINQ to DB doesn't know how to connect to our database or which POCOs go with what database. All this mapping is done through a DataConnection
class:
public class DbNorthwind : LinqToDB.Data.DataConnection
{
public DbNorthwind() : base("Northwind") { }
public ITable<Product> Product => GetTable<Product>();
public ITable<Category> Category => GetTable<Category>();
// ... other tables ...
}
We call the base constructor with the "Northwind" parameter. This parameter (called configuration name
) has to match the name="Northwind"
we defined above in our connection string. We also have to register our Product
class we defined above to allow us to write LINQ queries.
And now let's get some data:
using LinqToDB;
using LinqToDB.Common;
public static List<Product> All()
{
using (var db = new DbNorthwind())
{
var query = from p in db.Product
where p.ProductID > 25
orderby p.Name descending
select p;
return query.ToList();
}
}
Make sure you always wrap your DataConnection
class (in our case DbNorthwind
) in a using
statement. This is required for proper resource management, like releasing the database connections back into the pool. More details
Queries
Selecting Columns
Most times we get the entire row from the database:
from p in db.Product
where p.ProductID == 5
select p;
However, sometimes getting all the fields is too wasteful so we want only certain fields, but still use our POCOs; something that is challenging for libraries that rely on object tracking, like LINQ to SQL.
from p in db.Product
orderby p.Name descending
select new Product
{
Name = p.Name
};
Composing queries
Rather than concatenating strings we can 'compose' LINQ expressions. In the example below the final SQL will be different if onlyActive
is true or false, or if searchFor
is not null.
public static List<Product> All(bool onlyActive, string searchFor)
{
using (var db = new DbNorthwind())
{
var products = from p in db.Product
select p;
if (onlyActive)
{
products = from p in products
where !p.Discontinued
select p;
}
if (searchFor != null)
{
products = from p in products
where p.Name.Contains(searchFor)
select p;
}
return products.ToList();
}
}
Paging
A lot of times we need to write code that returns only a subset of the entire dataset. We expand on the previous example to show what a product search function could look like.
Keep in mind that the code below will query the database twice. Once to find out the total number of records, something that is required by many paging controls, and once to return the actual data.
public static List<Product> Search(
string searchFor,
int currentPage,
int pageSize,
out int totalRecords)
{
using (var db = new DbNorthwind())
{
var products = from p in db.Product
select p;
if (searchFor != null)
{
products = from p in products
where p.Name.Contains(searchFor)
select p;
}
totalRecords = products.Count();
return products.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
}
}
Joins
This assumes we added a Category
class, just like we did with the Product
class, defined all the fields, and registered it in our DbNorthwind
data access class. We can now write an INNER JOIN query like this:
from p in db.Product
join c in db.Category on p.CategoryID equals c.CategoryID
select new Product
{
Name = p.Name,
Category = c
};
and a LEFT JOIN query like this:
from p in db.Product
from c in db.Category.Where(q => q.CategoryID == p.CategoryID).DefaultIfEmpty()
select new Product
{
Name = p.Name,
Category = c
};
Creating your POCOs
In the previous example we assign an entire Category
object to our product, but what if we want all the fields in our Product
class, but we don't want to specify every field by hand? Unfortunately, we cannot write this:
from p in db.Product
from c in db.Category.Where(q => q.CategoryID == p.CategoryID).DefaultIfEmpty()
select new Product(c);
The query above assumes the Product class has a constructor that takes in a Category object. The query above won't work, but we can work around that with the following query:
from p in db.Product
from c in db.Category.Where(q => q.CategoryID == p.CategoryID).DefaultIfEmpty()
select Product.Build(p, c);
For this to work, we need a function in the Product
class that looks like this:
public static Product Build(Product product, Category category)
{
if (product != null)
{
product.Category = category;
}
return product;
}
One caveat with this approach is that if you're using it with composed queries (see example above) the select Build part has to come only in the final select.
Insert
At some point we will need to add a new Product
to the database. One way would be to call the Insert
extension method found in the LinqToDB
namespace; so make sure you import that.
using LinqToDB;
using (var db = new DbNorthwind())
{
db.Insert(product);
}
This inserts all the columns from our Product class, but without retrieving the generated identity value. To do that we can use InsertWith*Identity
methods, like this:
using LinqToDB;
using (var db = new DbNorthwind())
{
product.ProductID = db.InsertWithInt32Identity(product);
}
There is also InsertOrReplace
that updates a database record if it was found by primary key or adds it otherwise.
If you need to insert only certain fields, or use values generated by the database, you could write:
using LinqToDB;
using (var db = new DbNorthwind())
{
db.Product
.Value(p => p.Name, product.Name)
.Value(p => p.UnitPrice, 10.2m)
.Value(p => p.Added, () => Sql.CurrentTimestamp)
.Insert();
}
Use of this method also allows us to build insert statements like this:
using LinqToDB;
using (var db = new DbNorthwind())
{
var statement = db.Product
.Value(p => p.Name, product.Name)
.Value(p => p.UnitPrice, 10.2m);
if (storeAdded) statement.Value(p => p.Added, () => Sql.CurrentTimestamp);
statement.Insert();
}
Update
Updating records follows similar pattern to Insert. We have an extension method that updates all the columns in the database:
using LinqToDB;
using (var db = new DbNorthwind())
{
db.Update(product);
}
And we also have a lower level update mechanism:
using LinqToDB;
using (var db = new DbNorthwind())
{
db.Product
.Where(p => p.ProductID == product.ProductID)
.Set(p => p.Name, product.Name)
.Set(p => p.UnitPrice, product.UnitPrice)
.Update();
}
Similarly, we can break an update query into multiple pieces if needed:
using LinqToDB;
using (var db = new DbNorthwind())
{
var statement = db.Product
.Where(p => p.ProductID == product.ProductID)
.Set(p => p.Name, product.Name);
if (updatePrice) statement = statement.Set(p => p.UnitPrice, product.UnitPrice);
statement.Update();
}
You're not limited to updating a single record. For example, we could discontinue all the products that are no longer in stock:
using LinqToDB;
using (var db = new DbNorthwind())
{
db.Product
.Where(p => p.UnitsInStock == 0)
.Set(p => p.Discontinued, true)
.Update();
}
Delete
Similar to how you update records, you can also delete records:
using LinqToDB;
using (var db = new DbNorthwind())
{
db.Product
.Where(p => p.Discontinued)
.Delete();
}
Bulk Copy
Bulk copy feature supports the transfer of large amounts of data into a table from another data source. For more details read this article.
using LinqToDB.Data;
[Table("ProductsTemp")]
public class ProductTemp
{
[PrimaryKey]
public int ProductID { get; set; }
[Column("ProductName"), NotNull]
public string Name { get; set; }
// ... other columns ...
}
var list = new List<ProductTemp>();
// ... populate list ...
using (var db = new DbNorthwind())
{
db.BulkCopy(list);
}
Transactions
Using database transactions is easy. All you have to do is call BeginTransaction() on your DataConnection, run one or more queries, and then commit the changes by calling CommitTransaction(). If something happened and you need to roll back your changes you can either call RollbackTransaction() or throw an exception.
using (var db = new DbNorthwind())
{
db.BeginTransaction();
// ... select / insert / update / delete ...
if (somethingIsNotRight)
{
db.RollbackTransaction();
}
else
{
db.CommitTransaction();
}
}
Also, you can use .NET built-in TransactionScope class:
// don't forget that isolation level is serializable by default
using (var transaction = new TransactionScope())
// or for async code
// using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
using (var db = new DbNorthwind())
{
...
}
transaction.Complete();
}
It should be noted that there are two base classes for your "context" class: LinqToDB.Data.DataConnection
and LinqToDB.DataContext
. The key difference between them is in connection retention behaviour. DataConnection
opens connection with first query and holds it open until dispose happens. DataContext
behaves the way you might used to with Entity Framework: it opens connection per query and closes it right after query is done.
This difference in behavior matters when used with TransactionScope
:
using var db = new LinqToDB.Data.DataConnection("provider name", "connection string");
var product = db.GetTable<Product>()
.FirstOrDefault(); // connection opened here
var scope = new TransactionScope();
// this transaction was not attached to connection
// because it was opened earlier
product.Name = "Lollipop";
db.Update(product);
scope.Dispose();
// no transaction rollback happed, "Lollipop" has been saved
A DataConnection
is attached with ambient transaction in moment it is opened. Any TransactionScope
s created after the connection is created will no effect on that connection. Replacing DataConnection
with DataContext
in code shown earlier will make transaction scope work as expected: the created record will be discarded with the transaction.
Although, DataContext
appears to be the right class to choose, it is strongly recommended to use DataConnection
instead. It's default behaviour might be changed with setting CloseAfterUse
property to true
:
public class DbNorthwind : LinqToDB.Data.DataConnection
{
public DbNorthwind() : base("Northwind")
{
(this as IDataContext).CloseAfterUse = true;
}
}
Merge
Here you can read about MERGE support.
Window (Analytic) Functions
Here you can read about Window (Analytic) Functions support.
MiniProfiler
If you would like to use MiniProfiler or other profiling tool that wraps ADO.NET provider classes, you need to configure our regular DataConnection to use wrapped connection.
// example of SQL Server-backed data connection with MiniProfiler enabled for debug builds
public class DbDataContext : DataConnection
{
// let's use profiler only for debug builds
#if !DEBUG
// regular non-profiled constructor
public DbDataContext() : base("Northwind") {}
#else
// use static instance of mapping schema
// never create mapping schema per-connection
// or it will seriously affect performance
private static readonly MappingSchema _miniProfilerMappings = new ();
static DbDataContext()
{
// this is important part:
// here we tell linq2db how to access underlying ADO.NET classes of used provider
// if you don't configure those mappings, linq2db will be unable to use
// provider-specific functionality which could lead to loss or unavailability
//of some functionality when profiled connection enabled
_miniProfilerMappings.SetConvertExpression<ProfiledDbConnection, IDbConnection> (
db => db.WrappedConnection);
_miniProfilerMappings.SetConvertExpression<ProfiledDbDataReader, IDataReader> (
db => db.WrappedReader);
_miniProfilerMappings.SetConvertExpression<ProfiledDbTransaction, IDbTransaction>(
db => db.WrappedTransaction);
_miniProfilerMappings.SetConvertExpression<ProfiledDbCommand, IDbCommand> (
db => db.InternalCommand);
}
public DbDataContext()
: base(
// get data provider instance using
// <DB_NAME>Tools.GetDataProvider()
// helpers
// In this case we use SQL Server provider
SqlServerTools.GetDataProvider(SqlServerVersion.v2012),
GetConnection(),
_miniProfilerMappings)
{ }
// wrap connection into profiler wrapper
private static IDbConnection GetConnection()
{
// create provider-specific connection instance. SqlConnection in our case
var dbConnection = new SqlConnection(
@"Server=.\SQL;Database=Northwind;Trusted_Connection=True;Enlist=False;");
// wrap it by profiler's connection implementation
return new StackExchange.Profiling.Data.ProfiledDbConnection(
dbConnection,
MiniProfiler.Current);
}
#endif
}
More
Still have questions left? Check out our documentation site and FAQ
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. 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 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 is compatible. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net45 is compatible. net451 was computed. net452 was computed. net46 is compatible. net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. 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. |
-
.NETCoreApp 3.1
- No dependencies.
-
.NETFramework 4.5
- No dependencies.
-
.NETFramework 4.6
- No dependencies.
-
.NETFramework 4.7.2
- Microsoft.Bcl.AsyncInterfaces (>= 6.0.0)
-
.NETStandard 2.0
- Microsoft.Bcl.AsyncInterfaces (>= 6.0.0)
- Microsoft.CSharp (>= 4.7.0)
- System.ComponentModel.Annotations (>= 5.0.0)
- System.Data.DataSetExtensions (>= 4.5.0)
-
.NETStandard 2.1
- Microsoft.CSharp (>= 4.7.0)
- System.ComponentModel.Annotations (>= 5.0.0)
-
net6.0
- No dependencies.
NuGet packages (114)
Showing the top 5 NuGet packages that depend on linq2db:
Package | Downloads |
---|---|
linq2db.EntityFrameworkCore
Allows to execute Linq to DB (linq2db) queries in Entity Framework Core DbContext. |
|
linq2db.AspNet
LINQ to DB ASP.NET Core Extensions adds ability to configure ASP.NET Core application for Linq To DB usage. |
|
linq2db.PostgreSQL
LINQ to PostgreSQL is a data access technology that provides a run-time infrastructure for managing relational data as objects. Install this package only if you want to use database model scaffolding using T4 templates (requires Visual Studio or Rider), otherwise you should use linq2db package. |
|
linq2db.SqlServer
LINQ to SqlServer is a data access technology that provides a run-time infrastructure for managing relational data as objects. Install this package only if you want to use database model scaffolding using T4 templates (requires Visual Studio or Rider), otherwise you should use linq2db package. |
|
linq2db.MySql
LINQ to MySql is a data access technology that provides a run-time infrastructure for managing relational data as objects. Install this package only if you want to use database model scaffolding using T4 templates (requires Visual Studio or Rider), otherwise you should use linq2db package. |
GitHub repositories (16)
Showing the top 5 popular GitHub repositories that depend on linq2db:
Repository | Stars |
---|---|
bitwarden/server
Bitwarden infrastructure/backend (API, database, Docker, etc).
|
|
nopSolutions/nopCommerce
ASP.NET Core eCommerce software. nopCommerce is a free and open-source shopping cart.
|
|
mikependon/RepoDB
A hybrid ORM library for .NET.
|
|
SteveDunn/Vogen
A semi-opinionated library which is a source generator and a code analyser. It Source generates Value Objects
|
|
ClosedXML/ClosedXML.Report
ClosedXML.Report is a tool for report generation with which you can easily export any data from your .NET classes to Excel using a XLSX-template.
|
Version | Downloads | Last updated |
---|---|---|
6.0.0-preview.1 | 5,779 | 6/17/2024 |
5.4.1 | 536,913 | 4/7/2024 |
5.4.0 | 424,728 | 2/20/2024 |
5.3.2 | 558,843 | 10/18/2023 |
5.3.1 | 118,140 | 10/16/2023 |
5.3.0 | 23,758 | 10/12/2023 |
5.2.2 | 376,790 | 6/8/2023 |
5.2.1 | 388,624 | 5/18/2023 |
5.2.0 | 83,750 | 5/4/2023 |
5.1.1 | 88,325 | 3/25/2023 |
5.1.0 | 118,588 | 3/16/2023 |
5.0.0 | 104,216 | 2/23/2023 |
5.0.0-rc.2 | 698 | 2/16/2023 |
5.0.0-rc.1 | 417 | 2/9/2023 |
5.0.0-preview.2 | 891 | 2/2/2023 |
5.0.0-preview.1 | 1,568 | 1/12/2023 |
4.4.1 | 159,247 | 2/2/2023 |
4.4.0 | 407,943 | 12/15/2022 |
4.3.0 | 755,589 | 10/1/2022 |
4.2.0 | 147,579 | 9/1/2022 |
4.1.1 | 231,018 | 7/7/2022 |
4.1.0 | 100,725 | 6/16/2022 |
4.0.1 | 165,446 | 5/27/2022 |
4.0.0 | 44,864 | 5/19/2022 |
3.7.0 | 440,685 | 4/7/2022 |
3.6.0 | 858,993 | 11/15/2021 |
3.5.2 | 185,435 | 11/11/2021 |
3.5.1 | 88,057 | 10/22/2021 |
3.5.0 | 126,073 | 10/14/2021 |
3.4.5 | 35,664 | 10/2/2021 |
3.4.4 | 109,492 | 9/10/2021 |
3.4.3 | 95,406 | 8/13/2021 |
3.4.2 | 142,239 | 7/9/2021 |
3.4.1 | 45,317 | 7/1/2021 |
3.4.0 | 158,934 | 6/3/2021 |
3.3.0 | 911,781 | 3/25/2021 |
3.2.3 | 524,300 | 1/4/2021 |
3.2.2 | 39,953 | 12/26/2020 |
3.2.1 | 25,270 | 12/17/2020 |
3.2.0 | 15,200 | 12/17/2020 |
3.1.6 | 217,038 | 10/31/2020 |
3.1.5 | 567,520 | 10/15/2020 |
3.1.4 | 34,361 | 10/8/2020 |
3.1.3 | 59,845 | 9/17/2020 |
3.1.2 | 85,351 | 9/3/2020 |
3.1.1 | 52,046 | 8/27/2020 |
3.1.0 | 40,193 | 8/20/2020 |
3.0.1 | 133,248 | 7/13/2020 |
3.0.0 | 56,522 | 7/10/2020 |
3.0.0-rc.2 | 548 | 7/5/2020 |
3.0.0-rc.1 | 12,562 | 6/17/2020 |
3.0.0-rc.0 | 6,933 | 5/30/2020 |
3.0.0-preview.2 | 58,293 | 3/28/2020 |
3.0.0-preview.1 | 22,311 | 10/17/2019 |
2.9.8 | 802,137 | 4/16/2020 |
2.9.7 | 131,863 | 3/5/2020 |
2.9.6 | 384,056 | 1/30/2020 |
2.9.5 | 98,397 | 12/30/2019 |
2.9.4 | 377,891 | 11/12/2019 |
2.9.3 | 72,399 | 10/30/2019 |
2.9.2 | 52,061 | 10/17/2019 |
2.9.1 | 56,200 | 10/3/2019 |
2.9.0 | 118,182 | 8/8/2019 |
2.8.1.1 | 450 | 3/2/2024 |
2.8.1 | 39,963 | 7/29/2019 |
2.8.0 | 45,352 | 7/25/2019 |
2.7.4 | 113,771 | 6/14/2019 |
2.7.3 | 14,125 | 6/13/2019 |
2.7.2 | 40,044 | 6/1/2019 |
2.7.1 | 18,949 | 5/23/2019 |
2.7.0 | 134,161 | 4/25/2019 |
2.6.4 | 205,924 | 2/2/2019 |
2.6.3 | 31,480 | 1/20/2019 |
2.6.2 | 38,004 | 1/3/2019 |
2.6.1 | 27,023 | 12/21/2018 |
2.6.0 | 23,397 | 12/14/2018 |
2.5.4 | 70,174 | 11/21/2018 |
2.5.3 | 22,384 | 11/20/2018 |
2.5.2 | 202,823 | 11/12/2018 |
2.5.1 | 22,863 | 11/5/2018 |
2.5.0 | 32,248 | 11/1/2018 |
2.4.0 | 42,040 | 10/4/2018 |
2.3.0 | 76,880 | 8/30/2018 |
2.2.0 | 75,671 | 7/26/2018 |
2.1.0 | 33,109 | 6/21/2018 |
2.0.0 | 30,767 | 5/17/2018 |
1.10.2 | 46,138 | 1/27/2018 |
1.10.1 | 10,001 | 11/25/2017 |
1.10.0 | 8,817 | 11/19/2017 |
1.9.0 | 23,878 | 8/30/2017 |
1.8.3 | 30,350 | 7/5/2017 |
1.8.2 | 9,391 | 6/5/2017 |
1.8.1 | 2,729 | 6/3/2017 |
1.8.0 | 7,859 | 5/12/2017 |
1.7.6 | 17,074 | 2/19/2017 |
1.7.5 | 9,963 | 12/11/2016 |
1.0.7.4 | 55,131 | 4/13/2016 |
1.0.7.3 | 46,456 | 9/7/2015 |
1.0.7.2 | 7,585 | 8/13/2015 |
1.0.7.1 | 44,013 | 2/25/2015 |