使用共生微型 ORM 进行并行查询






4.67/5 (5投票s)
使用共生微型 ORM 执行并行查询
引言
本文将解释如何并行运行查询并使用共生 ORM 返回结果。 我们还将解释如何解决查询出现错误的情况,以及如何隔离问题查询。
共生是一个免费的 .NET ORM,支持以下数据库供应商:SQL Server、SQL Azure、MySQL、Sqlite、Oracle、PostgreSql、Firebird、DB2/LUW。
本文将重点介绍 SQL Server 数据库。
本文假设您对 C# 和 SQL Server 有很强的了解。
背景
您将需要一个 SQL Server 数据库,它可以是本地数据库文件、服务器数据库或 Azure SQL 数据库。
请确保将您的项目构建为 x64。 请参见菜单:“生成 \ 配置管理器”。
步骤 1:创建 TestItem1、TestItem2 表
运行以下 SQL 脚本来创建我们将用于本文的表。
CREATE TABLE [dbo].[TestItem1](
[TestId] [int] IDENTITY(1,1) NOT NULL,
[StringData] [nvarchar](50) NOT NULL,
[DateData] [datetime] NOT NULL
) ON [PRIMARY];
CREATE TABLE [dbo].[TestItem2](
[TestId] [int] IDENTITY(1,1) NOT NULL,
[StringData] [nvarchar](50) NOT NULL,
[DateData] [datetime] NOT NULL
) ON [PRIMARY];
步骤 2:创建一个项目并添加共生 ORM NuGet 包
在 Visual Studio 中为 .NET 4.6.1 或更高版本创建一个新的 C# 控制台项目。
然后添加 Nuget 包“Symbiotic_Micro_ORM_Net_Standard_x64
”。 您可以使用主菜单:“项目 \ 管理 Nuget 包...”
您可能需要在“解决方案资源管理器”中刷新项目以更新引用。
步骤 3:创建 TestItem1 和 TestItem2 类
这些类将用于表示您在步骤 1 中创建的表。
[DatabaseTable("TestItem1"), DebuggerDisplay("TestItem1: {TestId} {DateData} {StringData}")]
public class TestItem1
{
[DatabaseColumnAttribute("TestId", IsPrimaryKey = true, IsIdentityColumn = true)]
public int TestId { get; set; }
[DatabaseColumnAttribute("StringData")]
public string StringData { get; set; }
[DatabaseColumnAttribute("DateData")]
public DateTime DateData { get; set; }
}
[DatabaseTable("TestItem2"), DebuggerDisplay("TestItem2: {TestId} {DateData} {StringData}")]
public class TestItem2
{
[DatabaseColumnAttribute("TestId", IsPrimaryKey = true, IsIdentityColumn = true)]
public int TestId { get; set; }
[DatabaseColumnAttribute("StringData")]
public string StringData { get; set; }
[DatabaseColumnAttribute("DateData")]
public DateTime DateData { get; set; }
}
步骤 4:为共生 ORM 添加 Usings
将以下 using
行添加到“Program
”类的顶部。
using FrozenElephant.Symbiotic;
using FrozenElephant.Symbiotic.DataProviderSqlServer; // Using the Sql Server data provider
步骤 5:初始化工厂类
在“Main
”方法的开头添加以下代码行。
这些行初始化 factory
类并设置数据库连接字符串。
您需要修改连接字符串以匹配您的数据库、服务器和用户/密码。
// Initialize the factory and set the connection string
_DBTypesFactory = new DatabaseTypesFactorySqlServer(); // using sql server provider
_DBTypesFactory.ConnectionString = "Data Source=yourServer;
Initial Catalog=yourDatabase;User ID=ZZZZZZZ;Password=XXXXXX;Connect Timeout=35;
Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;
MultiSubnetFailover=False;MultipleActiveResultSets=true;Enlist=false";
您的“Program
”类现在应该如下面的代码所示
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using FrozenElephant.Symbiotic;
using FrozenElephant.Symbiotic.DataProviderSqlServer; // Using the SQL Server data provider
namespace Advanced_Parallel_Queries_With_Symbiotic_CS
{
// Make sure the build is set to x64
class Program
{
// the factory is where all Symbiotic ORM objects are created,
// this allows the developer to override creation as needed.
private static IDatabaseTypesFactory _DBTypesFactory;
static void Main(string[] args)
{
// Initialize the factory and set the connection string
_DBTypesFactory = new DatabaseTypesFactorySqlServer(); // using SQL Server provider
_DBTypesFactory.ConnectionString = "Data Source=yourServer;
Initial Catalog=yourDatabase;User ID=ZZZZZZZ;Password=XXXXXX;
Connect Timeout=35;Encrypt=False;TrustServerCertificate=True;
ApplicationIntent=ReadWrite;MultiSubnetFailover=False;
MultipleActiveResultSets=true;Enlist=false";
}
}
}
步骤 6:添加创建测试记录的方法
将以下方法添加到“Program
”类。
以下方法将用于创建稍后我们将查询的测试记录。
public static void CreateRandomItems()
{
IList<testitem1> items = new List<testitem1>();
for (int t = 0; t <= 1000; t++)
{
var emp = new TestItem1();
emp.DateData = DateTime.Now;
emp.StringData = Guid.NewGuid().ToString();
items.Add(emp);
}
IObjectWriter writer = _DBTypesFactory.CreateObjectWriter();
writer.InsertUpdate(items);
}
public static void CreateRandomItems2()
{
IList<testitem2> items = new List<testitem2>();
for (int t = 0; t <= 1000; t++)
{
var emp = new TestItem2();
emp.DateData = DateTime.Now;
emp.StringData = Guid.NewGuid().ToString();
items.Add(emp);
}
IObjectWriter writer = _DBTypesFactory.CreateObjectWriter();
writer.InsertUpdate(items);
}
步骤 7:将以下行添加到“Main”方法
将以下方法调用添加到“Main
”方法的末尾。
这些调用将创建用于稍后查询的记录。
// Create test records
CreateRandomItems();
CreateRandomItems2();
步骤 8:创建并行加载方法
此方法演示了并行运行多个查询并返回包含 TestItem1
和 TestItem2
项集合的集合。
我们构建一个 ISqlQuery
项的集合并调用“loader.ParallelLoadItems
”来并行运行查询。
public static void ParallelLoadItems()
{
//build a collection of queries to run
IList<isqlquery> queries = new List<isqlquery>();
ISqlQuery s1 = _DBTypesFactory.CreateSqlQuery
("Select * from TestItem1", "ParallelLoads.ParallelLoadItems1", typeof(TestItem1));
s1.AddRowLimit(_DBTypesFactory.DatabaseType, 2000);
queries.Add(s1);
ISqlQuery e1 = _DBTypesFactory.CreateSqlQuery("Select *
from TestItem1", "ParallelLoads.ParallelLoadItems2", typeof(TestItem1));
e1.AddRowLimit(_DBTypesFactory.DatabaseType, 2000);
queries.Add(e1);
ISqlQuery a1 = _DBTypesFactory.CreateSqlQuery("Select *
from TestItem2", "ParallelLoads.ParallelLoadItems3", typeof(TestItem2));
a1.AddRowLimit(_DBTypesFactory.DatabaseType, 2000);
queries.Add(a1);
ISqlQuery p1 = _DBTypesFactory.CreateSqlQuery("Select *
from TestItem1", "ParallelLoads.ParallelLoadItems4", typeof(TestItem1));
p1.AddRowLimit(_DBTypesFactory.DatabaseType, 2000);
queries.Add(p1);
IObjectLoader loader = _DBTypesFactory.CreateObjectLoader();
IList<ilist> data = loader.ParallelLoadItems(queries);
// demonstrates that the list is in the same order
// and how to cast the collection for use
IList<testitem2> items = (IList<testitem2>)data[2];
items[2].StringData = "Found it!";
}
步骤 9:问题规划
此方法将演示其中一个 SQL 查询中的错误,以及如何隔离问题查询并帮助您解决问题。 查询 2 有一个明显的错误,旨在帮助演示运行多个查询时隔离问题。
请注意,为错误查询传入的 SQL 标签是“my query 2
”,ORM 会在运行查询时将其包含在任何错误中。 如果您在“int a = 1;
”行添加一个断点,它将停在那里。
public static void ParallelLoadItemsError()
{
try
{
IList<isqlquery> queries = new List<isqlquery>();
ISqlQuery s1 = _DBTypesFactory.CreateSqlQuery("Select *
from TestItem1", "my query 1", typeof(TestItem1));
s1.AddRowLimit(_DBTypesFactory.DatabaseType, 2000);
queries.Add(s1);
ISqlQuery e1 = _DBTypesFactory.CreateSqlQuery("Select FakeCol1,
FakeCol2 from TestItem1", "my query 2", typeof(TestItem1));
queries.Add(e1);
ISqlQuery a1 = _DBTypesFactory.CreateSqlQuery("Select *
from TestItem2", "my query 3", typeof(TestItem2));
a1.AddRowLimit(_DBTypesFactory.DatabaseType, 2000);
queries.Add(a1);
ISqlQuery p1 = _DBTypesFactory.CreateSqlQuery("Select *
from TestItem1", "my query 4", typeof(TestItem1));
p1.AddRowLimit(_DBTypesFactory.DatabaseType, 2000);
queries.Add(p1);
IObjectLoader loader = _DBTypesFactory.CreateObjectLoader();
IList<ilist> data = loader.ParallelLoadItems(queries);
}
catch (Exception ex)
{
if (ex.InnerException.InnerException.Message.Contains("my query 2") == true)
{
int a = 1;
}
}
}
步骤 10:添加对并行方法的调用
将以下方法调用添加到“Main
”方法的末尾。
// perform parallel load
ParallelLoadItems();
// perform parallel load with a error
ParallelLoadItemsError();
关注点
本文仅触及了“共生”ORM 功能的表面。 有关更高级功能和示例的详细信息,请下载 nuget 包并查看包文件夹中的示例项目。
还有一个配套应用程序可以为现有数据库创建 POCO 类
历史
- 2019 年 6 月 27 日:初始版本