{"id":13486101,"url":"https://github.com/linq2db/linq2db","last_synced_at":"2025-05-13T18:07:24.846Z","repository":{"id":37382066,"uuid":"1916228","full_name":"linq2db/linq2db","owner":"linq2db","description":"Linq to database provider.","archived":false,"fork":false,"pushed_at":"2025-05-10T11:14:58.000Z","size":520786,"stargazers_count":3085,"open_issues_count":371,"forks_count":467,"subscribers_count":151,"default_branch":"master","last_synced_at":"2025-05-10T11:24:29.504Z","etag":null,"topics":["access","bulk-inserts","clickhouse","database","db2","dotnet","firebird","informix","linq","mariadb","mssql","mysql","oracle","orm","postgresql","sap-hana","sql","sqlce","sqlite","sqlserver"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/linq2db.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"MIT-LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2011-06-18T16:24:37.000Z","updated_at":"2025-05-09T13:40:20.000Z","dependencies_parsed_at":"2022-07-11T22:31:42.453Z","dependency_job_id":"6a252e2e-f7c2-452e-b8cc-ade2600bdd45","html_url":"https://github.com/linq2db/linq2db","commit_stats":{"total_commits":5275,"total_committers":152,"mean_commits":"34.703947368421055","dds":0.5854028436018958,"last_synced_commit":"6e12a1386899913b359f1c0fb726d59afe2c9aa0"},"previous_names":[],"tags_count":148,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linq2db%2Flinq2db","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linq2db%2Flinq2db/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linq2db%2Flinq2db/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linq2db%2Flinq2db/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/linq2db","download_url":"https://codeload.github.com/linq2db/linq2db/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254000848,"owners_count":21997441,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["access","bulk-inserts","clickhouse","database","db2","dotnet","firebird","informix","linq","mariadb","mssql","mysql","oracle","orm","postgresql","sap-hana","sql","sqlce","sqlite","sqlserver"],"created_at":"2024-07-31T18:00:39.410Z","updated_at":"2025-05-13T18:07:24.792Z","avatar_url":"https://github.com/linq2db.png","language":"C#","readme":"# LINQ to DB\n\n[![Discord](https://img.shields.io/discord/1089930409577545948?label=discord)](https://discord.gg/PcV6pTXt4s) [![NuGet Version](https://img.shields.io/nuget/vpre/linq2db)](https://www.nuget.org/profiles/LinqToDB) [![License](https://img.shields.io/github/license/linq2db/linq2db)](https://github.com/linq2db/linq2db/blob/master/MIT-LICENSE.txt)\n [![\"good first issue\" tasks](https://img.shields.io/github/issues/linq2db/linq2db/good%20first%20issue.svg)](https://github.com/linq2db/linq2db/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n\n[![Master branch build](https://img.shields.io/azure-devops/build/linq2db/linq2db/5/master?label=build%20(master))](https://dev.azure.com/linq2db/linq2db/_build?definitionId=5\u0026_a=summary) [![Latest build](https://img.shields.io/azure-devops/build/linq2db/linq2db/5?label=build%20(latest))](https://dev.azure.com/linq2db/linq2db/_build?definitionId=5\u0026_a=summary)\n\nLINQ to DB is the fastest LINQ database access library offering a simple, light, fast, and type-safe layer between your POCOs and your database.\n\nArchitecturally 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.\n\nHowever, 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.\n\nIn other words **LINQ to DB is type-safe SQL**.\n\n**LINQ to DB** also very nice for F# developers (see Tests/FSharp and Source/LinqToDB.FSharp project for details).\n\nDevelopment version nugets [feeds](https://dev.azure.com/linq2db/linq2db/_artifacts/feed/linq2db) ([how to use](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-visual-studio#package-sources))\n\n## Standout Features\n\n- Rich Querying API:\n  - [Explicit Join Syntax](https://linq2db.github.io/articles/sql/Join-Operators.html) (In addition to standard LINQ join syntax)\n  - [CTE Support](https://linq2db.github.io/articles/sql/CTE.html)\n  - [Bulk Copy/Insert](https://linq2db.github.io/articles/sql/Bulk-Copy.html)\n  - [Window/Analytic Functions](https://linq2db.github.io/articles/sql/Window-Functions-%28Analytic-Functions%29.html)\n  - [Merge API](https://linq2db.github.io/articles/sql/merge/Merge-API-Description.html)\n- Extensibility:\n  - [Ability to Map Custom SQL to Static Functions](https://github.com/linq2db/linq2db/tree/master/Source/LinqToDB/Sql/)\n\nSee [Github.io documentation](https://linq2db.github.io/index.html) for more details.\n\n\u003c!-- You can visit our [blog](http://blog.linq2db.com/) --\u003e\n\nCode examples and demos can be found [here](https://github.com/linq2db/examples) or in [tests](https://github.com/linq2db/linq2db/tree/master/Tests/Linq).\n\n[Release notes](https://github.com/linq2db/linq2db/wiki/Releases-and-Roadmap) page.\n\n### Related Linq To DB and 3rd-party projects\n\n- [linq2db.EntityFrameworkCore](https://github.com/linq2db/linq2db/tree/master/Source/LinqToDB.EntityFrameworkCore) (adds support for linq2db functionality in EF.Core projects)\n- [LinqToDB.Identity](https://github.com/linq2db/LinqToDB.Identity) - ASP.NET Core Identity provider using Linq To DB\n- [LINQPad Driver](https://github.com/linq2db/linq2db.LINQPad)\n- [DB2 iSeries Provider](https://github.com/LinqToDB4iSeries/Linq2DB4iSeries)\n- [ASP.NET CORE 2 Template](https://github.com/David-Mawer/LINQ2DB-MVC-Core-2/tree/master/LINQ2DB-MVC-Core-2)\n- [ASP.NET CORE 3 Template with Angular](https://github.com/David-Mawer/LINQ2DB-AngularWebApp-Core-3)\n- [ASP.NET CORE 5 Template](https://github.com/David-Mawer/LINQ2DB-MVC-Core-5)\n- [PostGIS extensions for linq2db](https://github.com/apdevelop/linq2db-postgis-extensions)\n\nNotable open-source users:\n\n- [nopCommerce](https://github.com/nopSolutions/nopCommerce) - popular open-source e-commerce solution\n- [OdataToEntity](https://github.com/voronov-maxim/OdataToEntity) - library to create OData service from database context\n- [SunEngine](https://github.com/sunengine/SunEngine) - site, blog and forum engine\n\nUnmantained projects:\n\n- [IdentityServer4.LinqToDB](https://github.com/linq2db/IdentityServer4.LinqToDB) - IdentityServer4 persistence layer using Linq To DB\n\n## Configuring connection strings\n\n### Passing Into Constructor\n\nYou can simply pass connection string into `DataConnection` or `DataContext` constructor using [`DataOptions`](https://linq2db.github.io/api/LinqToDB.DataOptions.html) class.\n\nMinimal configuration example:\n\n```cs\nvar db = new DataConnection(\n  new DataOptions()\n    .UseSqlServer(@\"Server=.\\;Database=Northwind;Trusted_Connection=True;\"));\n```\n\nUse connection configuration action to setup SqlClient-specific authentication token:\n\n```cs\nvar options = new DataOptions()\n  .UseSqlServer(connectionString, SqlServerVersion.v2017, SqlServerProvider.MicrosoftDataSqlClient)\n  .UseBeforeConnectionOpened(cn =\u003e\n    {\n        ((SqlConnection)cn).AccessToken = accessToken;\n    });\n\n// pass configured options to data context constructor\nvar dc = new DataContext(options);\n```\n\n\u003e [!TIP]\n\u003e There are a lot of configuration methods on `DataOptions` you can use.\n\u003e\n\u003e [!TIP]\n\u003e It is recommended to create configured `DataOptions` instance once and use it everywhere. E.g. you can register it in your DI container.\n\u003e\n\n### Using Config File (.NET Framework)\n\nIn your `web.config` or `app.config` make sure you have a connection string (check [this file](https://github.com/linq2db/linq2db/blob/master/Source/LinqToDB/ProviderName.cs) for supported providers):\n\n```xml\n\u003cconnectionStrings\u003e\n  \u003cadd name=\"Northwind\" \n    connectionString = \"Server=.\\;Database=Northwind;Trusted_Connection=True;\" \n    providerName     = \"SqlServer\" /\u003e\n\u003c/connectionStrings\u003e\n```\n\n### Using Connection String Settings Provider\n\nAlternatively, you can implement custom settings provider with `ILinqToDBSettings` interface, for example:\n\n```cs\npublic class ConnectionStringSettings : IConnectionStringSettings\n{\n    public string ConnectionString { get; set; }\n    public string Name             { get; set; }\n    public string ProviderName     { get; set; }\n    public bool   IsGlobal         =\u003e false;\n}\n\npublic class MySettings : ILinqToDBSettings\n{\n    public IEnumerable\u003cIDataProviderSettings\u003e DataProviders\n        =\u003e Enumerable.Empty\u003cIDataProviderSettings\u003e();\n\n    public string DefaultConfiguration =\u003e \"SqlServer\";\n    public string DefaultDataProvider  =\u003e \"SqlServer\";\n\n    public IEnumerable\u003cIConnectionStringSettings\u003e ConnectionStrings\n    {\n        get\n        {\n            // note that you can return multiple ConnectionStringSettings instances here\n            yield return\n                new ConnectionStringSettings\n                {\n                    Name             = \"Northwind\",\n                    ProviderName     = ProviderName.SqlServer,\n                    ConnectionString =\n                        @\"Server=.\\;Database=Northwind;Trusted_Connection=True;\"\n                };\n        }\n    }\n}\n```\n\nAnd later just set on program startup before the first query is done (Startup.cs for example):\n\n```cs\nDataConnection.DefaultSettings = new MySettings();\n```\n\n### Use with ASP.NET Core and Dependency Injection\n\nSee [article](https://linq2db.github.io/articles/get-started/asp-dotnet-core/index.html).\n\n## Define **POCO** class\n\nYou can generate POCO classes from your database using [linq2db.cli](https://www.nuget.org/packages/linq2db.cli)  `dotnet tool`.\n\nAlternatively, you can write them manually and map to database using mapping attributes or `fluent mapping configuration`. Also you can use POCO classes as-is without additional mappings if they use same naming for classes and properties as table and column names in database.\n\n### Configuration using mapping attributes\n\n```c#\nusing System;\nusing LinqToDB.Mapping;\n\n[Table(\"Products\")]\npublic class Product\n{\n  [PrimaryKey, Identity]\n  public int ProductID { get; set; }\n\n  [Column(\"ProductName\"), NotNull]\n  public string Name { get; set; }\n\n  [Column]\n  public int VendorID { get; set; }\n\n  [Association(ThisKey = nameof(VendorID), OtherKey=nameof(Vendor.ID))]\n  public Vendor Vendor { get; set; }\n\n  // ... other columns ...\n}\n```\n\nThis approach involves attributes on all properties that should be mapped. This way lets you to configure all possible things linq2db ever supports. There is 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:\n\n```c#\nusing System;\nusing LinqToDB.Mapping;\n\n[Table(\"Products\")]\npublic class Product\n{\n  [PrimaryKey, Identity]\n  public int ProductID { get; set; }\n\n  // Property `Name` will be ignored as it lacks `Column` attibute.\n  public string Name { get; set; }\n}\n```\n\n### Fluent Configuration\n\nThis 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 their abilities. This kind of configuration is done through the class `MappingSchema`.\n\nWith Fluent approach you can configure only things that require it explicitly. All other properties will be inferred by linq2db:\n\n```c#\n// IMPORTANT: configure mapping schema instance only once\n// and use it with all your connections that need those mappings\n// Never create new mapping schema for each connection as\n// it will seriously harm performance\nvar myFluentMappings = new MappingSchema();\nvar builder       = new FluentMappingBuilder(mappingSchema);\n\nbuilder.Entity\u003cProduct\u003e()\n    .HasTableName(\"Products\")\n    .HasSchemaName(\"dbo\")\n    .HasIdentity(x =\u003e x.ProductID)\n    .HasPrimaryKey(x =\u003e x.ProductID)\n    .Ignore(x =\u003e x.SomeNonDbProperty)\n    .Property(x =\u003e x.TimeStamp)\n        .HasSkipOnInsert()\n        .HasSkipOnUpdate()\n    .Association(x =\u003e x.Vendor, x =\u003e x.VendorID, x =\u003e x.VendorID, canBeNull: false)\n    ;\n\n//... other mapping configurations\n\n// commit configured mappings to mapping schema\nbuilder.Build();\n```\n\nIn this example we configured only three properties and one association. We let Linq To DB to infer all other properties as columns with same name as property.\n\nTo use your `MappingSchema` instance you should pass it `DataConnection` or `DataContext` constructor:\n\n```cs\nvar options = new DataOptions()\n    .UseSqlServer(@\"Server=.\\;Database=Northwind;Trusted_Connection=True;\")\n    .UseMappingSchema(myFluentMappings);\n\nvar db = new DataConnection(option);\n```\n\n### Inferred Configuration\n\nThis approach involves no attributes at all. In this case Linq To DB 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:\n\n- Linq To DB will not infer primary key even if class has property called `ID`;\n- it will not infer nullability of reference types if you don't use nullable reference types annotations;\n- associations will not be automatically configured.\n\n```c#\nusing System;\nusing LinqToDB.Mapping;\n\npublic class Product\n{\n  public int    ProductID { get; set; }\n\n  public string Name      { get; set; }\n\n  public int    VendorID  { get; set; }\n\n  public Vendor Vendor    { get; set; }\n\n  // ... other columns ...\n}\n```\n\nThis way Linq To DB 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`.\n\nThis approach is not generally recommended.\n\n### DataConnection class\n\nAt 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:\n\n```c#\npublic class DbNorthwind : LinqToDB.Data.DataConnection\n{\n  public DbNorthwind() : base(\"Northwind\") { }\n\n  public ITable\u003cProduct\u003e  Product  =\u003e this.GetTable\u003cProduct\u003e();\n  public ITable\u003cCategory\u003e Category =\u003e this.GetTable\u003cCategory\u003e();\n\n  // ... other tables ...\n}\n```\n\nWe call the base constructor with the \"Northwind\" parameter. This parameter (called `configuration name`) has to match the `name=\"Northwind\"` we defined above as name of our connection string. We also added convenience properties for `Product` and `Category` mapping classes to write LINQ queries.\n\nAnd now let's get some data:\n\n```cs\nusing LinqToDB;\nusing LinqToDB.Common;\n\npublic static List\u003cProduct\u003e GetProducts()\n{\n  using var db = new DbNorthwind();\n\n  var query = from p in db.Product\n                where p.ProductID \u003e 25\n                orderby p.Name descending\n                select p;\n\n  return query.ToList();\n}\n```\n\nMake 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](https://linq2db.github.io/articles/general/Managing-data-connection.html)).\n\n## Queries\n\n### Selecting Columns\n\nMost times we get the entire row from the database:\n\n```c#\nfrom p in db.Product\nwhere p.ProductID == 5\nselect p;\n```\n\nHowever, 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.\n\n```c#\nfrom p in db.Product\norderby p.Name descending\nselect new Product\n{\n  Name = p.Name\n};\n```\n\n### Composing queries\n\nRather 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.\n\n```c#\npublic static Product[] GetProducts(bool onlyActive, string searchFor)\n{\n  using var db = new DbNorthwind();\n  var products = from p in db.Product \n                   select p;\n\n  if (onlyActive)\n  {\n    products = from p in products \n               where !p.Discontinued \n               select p;\n  }\n\n  if (searchFor != null)\n  {\n    products = from p in products \n                 where p.Name.Contains(searchFor) \n                 select p;\n  }\n\n  return products.ToArray();\n}\n```\n\n### Paging\n\nA 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.\n\nKeep 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.\n\n```c#\npublic static List\u003cProduct\u003e Search(\n                  string  searchFor,\n                  int     currentPage,\n                  int     pageSize,\n                  out int totalRecords)\n{\n  using var db = new DbNorthwind();\n  var products = from p in db.Product \n                   select p;\n\n  if (searchFor != null)\n  {\n    products = from p in products \n               where p.Name.Contains(searchFor) \n               select p;\n  }\n\n  totalRecords = products.Count();\n\n  return products.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();\n}\n```\n\n### Joins\n\nThis assumes we added a `Category` class, just like we did with the `Product` class, defined all the fields, and defined table access property in our `DbNorthwind` data access class. We can now write an **INNER JOIN** query like this:\n\n```c#\nfrom p in db.Product\njoin c in db.Category on p.CategoryID equals c.CategoryID\nselect new Product\n{\n  Name = p.Name,\n  Category = c\n};\n```\n\nand a **LEFT JOIN** query like this:\n\n```c#\nfrom p in db.Product\nfrom c in db.Category.Where(q =\u003e q.CategoryID == p.CategoryID).DefaultIfEmpty()\nselect new Product\n{\n  Name = p.Name,\n  Category = c\n};\n```\n\n[More samples are here](https://linq2db.github.io/articles/sql/Join-Operators.html)\n\n### Creating your POCOs\n\nIn 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:\n\n```c#\nfrom p in db.Product\nfrom c in db.Category.Where(q =\u003e q.CategoryID == p.CategoryID).DefaultIfEmpty()\nselect new Product(c);\n```\n\nThe 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:\n\n```c#\nfrom p in db.Product\nfrom c in db.Category.Where(q =\u003e q.CategoryID == p.CategoryID).DefaultIfEmpty()\nselect Product.Build(p, c);\n```\n\nFor this to work, we need a function in the `Product` class that looks like this:\n\n```c#\npublic static Product Build(Product? product, Category category)\n{\n  if (product != null)\n  {\n    product.Category = category;\n  }\n  return product;\n}\n```\n\nOne 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.\n\n### Insert\n\nAt 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.\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\ndb.Insert(product);\n```\n\nThis 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:\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\nproduct.ProductID = db.InsertWithInt32Identity(product);\n```\n\nThere is also `InsertOrReplace` that updates a database record if it was found by primary key or adds it otherwise.\n\nIf you need to insert only certain fields, or use values generated by the database, you could write:\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\ndb.Product\n  .Value(p =\u003e p.Name, product.Name)\n  .Value(p =\u003e p.UnitPrice, 10.2m)\n  .Value(p =\u003e p.Added, () =\u003e Sql.CurrentTimestamp)\n  .Insert();\n```\n\nUse of this method also allows us to build insert statements like this:\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\nvar statement = db.Product\n                    .Value(p =\u003e p.Name, product.Name)\n                    .Value(p =\u003e p.UnitPrice, 10.2m);\n\nif (storeAdded) statement.Value(p =\u003e p.Added, () =\u003e Sql.CurrentTimestamp);\n\nstatement.Insert();\n```\n\n### Update\n\nUpdating records follows similar pattern to `Insert`. We have an extension method that updates all the columns in the database:\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\ndb.Update(product);\n```\n\nAnd we also have a lower level update mechanism:\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\ndb.Product\n  .Where(p =\u003e p.ProductID == product.ProductID)\n  .Set(p =\u003e p.Name, product.Name)\n  .Set(p =\u003e p.UnitPrice, product.UnitPrice)\n  .Update();\n```\n\nSimilarly, we can break an update query into multiple pieces if needed:\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\nvar statement = db.Product\n                    .Where(p =\u003e p.ProductID == product.ProductID)\n                    .Set(p =\u003e p.Name, product.Name);\n\nif (updatePrice) statement = statement.Set(p =\u003e p.UnitPrice, product.UnitPrice);\n\nstatement.Update();\n```\n\nYou're not limited to a single record update. For example, we could discontinue all the products that are no longer in stock:\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\ndb.Product\n  .Where(p =\u003e p.UnitsInStock == 0)\n  .Set(p =\u003e p.Discontinued, true)\n  .Update();\n```\n\n### Delete\n\nSimilar to how you update records, you can also delete records:\n\n```c#\nusing LinqToDB;\n\nusing var db = new DbNorthwind();\ndb.Product\n  .Where(p =\u003e p.Discontinued)\n  .Delete();\n```\n\n### Bulk Copy\n\nBulk copy feature supports the transfer of large amounts of data into a table from another data source. For more details read this [article](https://linq2db.github.io/articles/sql/Bulk-Copy.html).\n\n```c#\nusing LinqToDB.Data;\n\n[Table(\"ProductsTemp\")]\npublic class ProductTemp\n{\n  [PrimaryKey]\n  public int ProductID { get; set; }\n\n  [Column(\"ProductName\"), NotNull]\n  public string Name { get; set; }\n\n  // ... other columns ...\n}\n\nvar list = new List\u003cProductTemp\u003e();\n\n// ... populate list ...\n\nusing var db = new DbNorthwind();\ndb.BulkCopy(list);\n```\n\n### Transactions\n\nUsing 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.\n\n```c#\nusing var db = new DbNorthwind();\ndb.BeginTransaction();\n// or\n//using var tr = db.BeginTransaction();\n  \n  // ... select / insert / update / delete ...\n\nif (somethingIsNotRight)\n{\n  db.RollbackTransaction();\n  // or\n  // tr.Rollback();\n}\nelse\n{\n  db.CommitTransaction();\n  // or\n  // tr.Commit();\n}\n```\n\nAlso, you can use .NET built-in `TransactionScope` class:\n\n```c#\nusing var transaction = new TransactionScope();\n// or for async code\n// using var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);\nusing var db = new DbNorthwind();\n...\ntransaction.Complete();\n```\n\nIt 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.\n\nThis difference in behavior matters when used with `TransactionScope`:\n\n```c#\nusing var db = new LinqToDB.Data.DataConnection(\"provider name\", \"connection string\");\n\nvar product = db.GetTable\u003cProduct\u003e()\n  .FirstOrDefault(); // connection opened here\n\nvar scope = new TransactionScope();\n// this transaction was not attached to connection\n// because it was opened earlier\n\nproduct.Name = \"Lollipop\";\ndb.Update(product);\n\nscope.Dispose();\n\n// no transaction rollback happed, \"Lollipop\" has been saved\n```\n\nA `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.\n\nAlthough, `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`:\n\n```c#\npublic class DbNorthwind : LinqToDB.Data.DataConnection\n{\n  public DbNorthwind() : base(\"Northwind\")\n  {\n    (this as IDataContext).CloseAfterUse = true;\n  }\n}\n```\n\n### Merge\n\n[Here](https://linq2db.github.io/articles/sql/merge/Merge-API.html) you can read about SQL MERGE support.\n\n### Window (Analytic) Functions\n\n[Here](https://linq2db.github.io/articles/sql/Window-Functions-%28Analytic-Functions%29.html) you can read about Window (Analytic) Functions support.\n\n## MiniProfiler\n\nIf you would like to use [MiniProfiler](https://github.com/MiniProfiler/dotnet) or other profiling tool that wraps ADO.NET provider classes, you need to configure our regular `DataConnection` to use wrapped connection.\n\n```c#\n// example of SQL Server-backed data connection with MiniProfiler enabled for debug builds\npublic class DbDataContext : DataConnection\n{\n// let's use profiler only for debug builds\n#if !DEBUG\n\n  // regular non-profiled constructor\n  public DbDataContext() : base(\"Northwind\") {}\n  \n#else\n  public DbDataContext()\n      : base(\n          new DataOptions()\n            .UseSqlServer(connectionString, SqlServerVersion.v2012)\n            .UseConnectionFactory(GetConnection)\n            .UseInterceptor(new UnwrapProfilerInterceptor()))\n  {\n  }\n\n  // wrap connection into profiler wrapper\n  private static DbConnection GetConnection(DataOptions options)\n  {\n     // create provider-specific connection instance. SqlConnection in our case\n     var dbConnection = new SqlConnection(options.ConnectionOptions.ConnectionString);\n\n     // wrap it by profiler's connection implementation\n     return new StackExchange.Profiling.Data.ProfiledDbConnection(\n                                                 dbConnection,\n                                                 MiniProfiler.Current);\n  }\n\n  // define UnwrapDataObjectInterceptor\n  sealed class UnwrapProfilerInterceptor : UnwrapDataObjectInterceptor\n  {\n    public override DbConnection UnwrapConnection(IDataContext dataContext, DbConnection connection)\n    {\n      return connection is ProfiledDbConnection c ? c.WrappedConnection : connection;\n    }\n\n    public override DbTransaction UnwrapTransaction(IDataContext dataContext, DbTransaction transaction)\n    {\n       return transaction is ProfiledDbTransaction t ? t.WrappedTransaction : transaction;\n    }\n\n    public override DbCommand UnwrapCommand(IDataContext dataContext, DbCommand command)\n    {\n      return command is ProfiledDbCommand c ? c.WrappedCommand : command;\n    }\n\n    public override DbDataReader UnwrapDataReader(IDataContext dataContext, DbDataReader dataReader)\n    {\n      return dataReader is ProfiledDbDataReader dr ? dr.WrappedReader : dataReader;\n    }\n  }\n#endif\n}\n```\n\n## F#\n\n### Sample query with load child relations \n\n```fsharp\nlet getPerson (db: IDataContext) (id: int) =\n    let persons = db.GetTable\u003cPerson\u003e().LoadWith(fun x -\u003e x.Patient)\n\n    let person =\n        query {\n            for p in persons do\n                where (p.ID = id)\n                exactlyOne\n        }\n\n    person\n```\n\n## More\n\nStill have questions left? Check out our [documentation site](https://linq2db.github.io) and [FAQ](https://linq2db.github.io/articles/FAQ.html)\n","funding_links":[],"categories":["C#","C# #","Libraries","C\\#","Language bindings","ORM","sql","Audio"],"sub_categories":["ORM and Micro-ORM","Queries","Other sdk/libraries","GUI - other"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinq2db%2Flinq2db","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinq2db%2Flinq2db","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinq2db%2Flinq2db/lists"}