{"id":31381646,"url":"https://github.com/faib920/fireasy3","last_synced_at":"2025-09-28T10:40:07.788Z","repository":{"id":152893192,"uuid":"624668702","full_name":"faib920/fireasy3","owner":"faib920","description":"Fireasy 3.0 是基于 .Net Core 应用开发组件，其主旨思想为“让开发变为更简单”，其义为，使用尽可能少的组件，实现你所需的功能。 Fireasy 提供最基础的功能和核心功能，如Emit、Aop，以及模块化、数据库访问、工作单元、多租户、实体仓储、分布式缓存、分布式锁、对象映射、事件总线（消息队列）等等功能。","archived":false,"fork":false,"pushed_at":"2023-06-14T15:55:25.000Z","size":10840,"stargazers_count":25,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"dev3.0","last_synced_at":"2025-08-22T21:18:07.330Z","etag":null,"topics":["aop","code-analyzer","database","distributed-lock","dotnet-core","dynamic","emit","entity-framework","event-bus","framework","object-mapper","orm"],"latest_commit_sha":null,"homepage":"http://www.fireasy.cn","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/faib920.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-04-07T01:39:42.000Z","updated_at":"2025-05-05T12:00:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"e68b5624-dccc-42db-ba74-5e7bc4c03a08","html_url":"https://github.com/faib920/fireasy3","commit_stats":{"total_commits":96,"total_committers":1,"mean_commits":96.0,"dds":0.0,"last_synced_commit":"4a84c29c96906550986fd904fc7fb44ac535a944"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/faib920/fireasy3","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faib920%2Ffireasy3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faib920%2Ffireasy3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faib920%2Ffireasy3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faib920%2Ffireasy3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/faib920","download_url":"https://codeload.github.com/faib920/fireasy3/tar.gz/refs/heads/dev3.0","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faib920%2Ffireasy3/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277315138,"owners_count":25797569,"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","status":"online","status_checked_at":"2025-09-27T02:00:08.978Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["aop","code-analyzer","database","distributed-lock","dotnet-core","dynamic","emit","entity-framework","event-bus","framework","object-mapper","orm"],"created_at":"2025-09-28T10:40:06.687Z","updated_at":"2025-09-28T10:40:07.774Z","avatar_url":"https://github.com/faib920.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fireasy 3.0\n----\n\n　　fireasy 3.0 在 2.0 的基础上进行了重构，抛弃了 `.Net Framework` 时代的一些思想和模式，使之完全与 `.Net Core` 相匹配。\n\n　　目前 3.0 还处于开发阶段，到正式发布还需要一段时间，感谢你的关注与支持。\n\n　　\u003cimg src=\"http://fireasy.cn/content/upload/donate_weixin.jpg\" style=\"height:240px\" /\u003e \u003cimg src=\"http://fireasy.cn/content/upload/qqgroup.png\" style=\"height:240px\" /\u003e\n\n## 一、目标框架\n　　目前目标框架为 `net462`、`netstandard2.0`、`netstandard2.1` 和 `net6.0`。\n\n## 二、部分程序集\n\n| 程序集 | 说明 |\n| :--- | :--- |\n|Fireasy.Common|公共类库，提供依赖注入、动态代理、代码编译、静态编译、反射缓存等等，以及各类基础接口的定义|\n|Fireasy.Composition|提供 MEF 的集成|\n|Fireasy.Common.Analyzers|Fireasy.Common 的语法分析类库，提供动态代理(AOP)生成、依赖服务发现与注入|\n|Fireasy.CodeCompiler.VisualBasic|提供代码编译对 VB.NET 语言支持|\n|Fireasy.Configuration|配置相关类库，提供配置的解析和配置|\n|Fireasy.Data.Abstractions|数据库抽象类库，定义数据库层面的各类接口、适配器接口(语法、架构、批量插入、记录包装等等)|\n|Fireasy.Data|数据库实现类库，对抽象类库的实现，提供SqlServer、MySql、SQLite、Firebird、PostgreSql、Oracle、达梦、人大金仓和神通数据库的适配|\n|Fireasy.Data.Configuration|数据库配置相关类库，提供数据库适配器及连接字符串的配置解析|\n|Fireasy.Data.OleDb|OleDb 适配|\n|Fireasy.Data.Analyzers|Fireasy.Data 的语法分析类库，提供 BulkCopy 适配器的生成|\n|Fireasy.Data.Entity.Abstractions|实体框架的抽象类库，定义 EntityContext、实体仓储等等|\n|Fireasy.Data.Entity|实体框架的具体实现，提供SqlServer、MySql、SQLite、Firebird、PostgreSql、Oracle、达梦、人大金仓和神通数据库的 linq 查询解析|\n|Fireasy.ObjectMapping.Abstractions|对象映射抽象类库，定义对象映射的接口|\n|Fireasy.AutoMapper|对象映射之 AutoMapper 适配|\n|Fireasy.Mapster|对象映射之 Mapster 适配|\n\n## 三、开始使用\n\n　　要使用 Fireasy 相关的组件，必须在 `IServiceCollection` 对象上使用扩展方法 `AddFireasy()`。\n\n### 1、Winform\n\n```csharp\nstatic class Program\n{\n    public static IServiceProvider ServiceProvider { get; set; }\n\n    [STAThread]\n    static void Main(params string[] args)\n    {\n        Application.EnableVisualStyles();\n        Application.SetCompatibleTextRenderingDefault(false);\n            \n        var services = new ServiceCollection();\n\n        //必不可少\n        services.AddFireasy();\n\n        var configuration = new ConfigurationBuilder()\n            .SetBasePath(Directory.GetCurrentDirectory())\n            .AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: true)\n            .Build();\n\n        services.AddSingleton\u003cIConfiguration\u003e(configuration);\n        ServiceProvider = services.BuildServiceProvider();\n\n        Application.Run(new frmMain());\n    }\n}\n```\n\n### 2、Console\n\n```csharp\nstatic class Program\n{\n    public static IServiceProvider ServiceProvider { get; set; }\n\n    static void Main(params string[] args)\n    {\n        var services = new ServiceCollection();\n\n        var configuration = new ConfigurationBuilder()\n            .SetBasePath(Directory.GetCurrentDirectory())\n            .AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: true)\n            .Build();\n\n        //必不可少\n        services.AddFireasy();\n\n        services.AddSingleton\u003cIConfiguration\u003e(configuration);\n        ServiceProvider = services.BuildServiceProvider();\n\n        Console.ReadKey();\n    }\n}\n```\n\n### 3、ASP.NET Core\n\n```csharp\npublic class Startup\n{\n    public Startup(IConfiguration configuration)\n    {\n        Configuration = configuration;\n    }\n\n    public IConfiguration Configuration { get; }\n\n    public void ConfigureServices(IServiceCollection services)\n    {\n        //必不可少\n        services.AddFireasy();\n    }\n}\n```\n\n## 四、公共类库\n\n### 1、服务发现\n\n* 使用 `Predicate` 对程序集进行过滤\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n\n    //只遍列 Fireasy.Common.Tests\n    services.AddFireasy(opt =\u003e opt.DiscoverOptions.AssemblyFilterPredicates.Add(s =\u003e !s.FullName!.StartsWith(\"Fireasy.Common.Tests\")));\n}\n```\n\n* 使用 `IAssemblyFilter` 对程序集进行过滤\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    services.AddFireasy(opt =\u003e opt.DiscoverOptions.AssemblyFilters.Add(new MyAssemblyFilter()));\n\n    private class MyAssemblyFilter : IAssemblyFilter\n    {\n        public bool IsFilter(Assembly assembly)\n        {\n            //只遍列 Fireasy.Common.Tests\n            return !assembly.FullName!.StartsWith(\"Fireasy.Common.Tests\");\n        }\n    }\n}\n```\n\n* 列出遍列过的程序集\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var discoverer = serviceProvider.GetRequiredService\u003cIServiceDiscoverer\u003e();\n\n    foreach (var assembly in discoverer.Assemblies)\n    {\n        Console.WriteLine(assembly.FullName);\n    }\n}\n```\n\n* 列出注册的所有服务描述\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var discoverer = serviceProvider.GetRequiredService\u003cIServiceDiscoverer\u003e();\n\n    foreach (var desc in discoverer.Descriptors)\n    {\n        Console.WriteLine($\"{desc.ServiceType} -\u003e {desc.ImplementationType}\");\n    }\n}\n```\n\n* 发现 `ISingletonService`、`ITransientService` 或 `IScopedService` 三种生命周期的服务\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var service1 = serviceProvider.GetService\u003cITestSingletonService\u003e();\n    var service2 = serviceProvider.GetService\u003cITestSingletonService\u003e();\n\n    Assert.IsNotNull(service1);\n    Assert.IsNotNull(service2);\n\n    //两对象的id应相等\n    Assert.AreEqual(service1.Id, service2.Id);\n\n    Guid id1, id2;\n\n    //作用域1\n    using (var scope1 = serviceProvider.CreateScope())\n    {\n        var service1 = scope1.ServiceProvider.GetService\u003cITestScopedService\u003e();\n        var service2 = scope1.ServiceProvider.GetService\u003cITestScopedService\u003e();\n\n        Assert.IsNotNull(service1);\n        Assert.IsNotNull(service2);\n\n        //两对象的id应相等\n        Assert.AreEqual(service1.Id, service2.Id);\n\n        id1 = service1.Id;\n    }\n\n    //作用域2\n    using (var scope2 = serviceProvider.CreateScope())\n    {\n        var service1 = scope2.ServiceProvider.GetService\u003cITestScopedService\u003e();\n        var service2 = scope2.ServiceProvider.GetService\u003cITestScopedService\u003e();\n\n        Assert.IsNotNull(service1);\n        Assert.IsNotNull(service2);\n\n        //两对象的id应相等\n        Assert.AreEqual(service1.Id, service2.Id);\n\n        id2 = service1.Id;\n    }\n\n    //两次scoped的id应不相等\n    Assert.AreNotEqual(id1, id2);\n}\n\npublic interface ITestSingletonService\n{\n    Guid Id { get; }\n\n    void Test();\n}\n\npublic class TestSingletonServiceImpl : ITestSingletonService, ISingletonService\n{\n    public TestSingletonServiceImpl()\n    {\n        Id = Guid.NewGuid();\n    }\n\n    public Guid Id { get; }\n\n    public void Test() =\u003e Console.WriteLine(\"Hello TestSingletonService!\");\n}\n\npublic interface ITestScopedService\n{\n    Guid Id { get; }\n\n    void Test();\n}\n\npublic class TestScopedServiceImpl : ITestScopedService, IScopedService\n{\n    public TestScopedServiceImpl()\n    {\n        Id = Guid.NewGuid();\n    }\n\n    public Guid Id { get; }\n\n    public void Test() =\u003e Console.WriteLine(\"Hello TestScopedService!\");\n}\n```\n\n* 使用服务部署器，自动注册服务\n\n```csharp\n[assembly: ServicesDeploy(typeof(DataServicesDeployer))]\n\npublic class DataServicesDeployer : IServicesDeployer\n{\n    void IServicesDeployer.Configure(IServiceCollection services)\n    {\n        services.AddSingleton\u003cIProviderManager, DefaultProviderManager\u003e();\n        services.AddSingleton\u003cIDatabaseFactory, DefaultDatabaseFactory\u003e();\n        services.AddSingleton\u003cIRowMapperFactory, DefaultRowMapperFactory\u003e();\n        services.AddSingleton\u003cIValueConvertManager, DefaultValueConvertManager\u003e();\n        services.AddScoped\u003cIDatabase\u003e(sp =\u003e sp.GetRequiredService\u003cIDatabaseFactory\u003e().CreateDatabase());\n    }\n}\n```\n\n### 2、动态代理\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var proxyFactory = serviceProvider.GetService\u003cIDynamicProxyFactory\u003e();\n    var proxyObj = proxyFactory!.BuildProxy\u003cTestProxy\u003e();\n\n    var value = await proxyObj!.GetStringAsync();\n    Assert.AreEqual(\"hello world\", value);\n}\n\npublic class TestProxy\n{\n    [Intercept(typeof(GetStringAsyncInterceptor))]\n    public virtual Task\u003cstring\u003e GetStringAsync()\n    {\n        return Task.FromResult(string.Empty);\n    }\n}\n\npublic class GetStringAsyncInterceptor : IAsyncInterceptor\n{\n    public ValueTask InitializeAsync(InterceptContext context)\n    {\n        return ValueTask.CompletedTask;\n    }\n\n    public ValueTask InterceptAsync(InterceptCallInfo info)\n    {\n        info.ReturnValue = \"hello world\";\n\n        return ValueTask.CompletedTask;\n    }\n}\n```\n\n### 3、反射缓存\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var reflectionFactory = serviceProvider.GetService\u003cIReflectionFactory\u003e();\n\n    var obj = new OneObject();\n    var property = typeof(OneObject).GetTypeInfo().GetDeclaredProperty(nameof(OneObject.Value));\n    var accessor = reflectionFactory!.GetAccessor\u003cint\u003e(property!);\n\n    accessor.SetValue(obj, 100);\n    var value = accessor.GetValue(obj);\n\n    Assert.AreEqual(100, value);\n}\n\nprivate class OneObject\n{\n    public int Value { get; set; }\n}\n```\n\n### 4、动态编译\n\n```csharp\nprivate void Test()\n{\n    /*\n    public class MyClass\u003cT, TS\u003e where T : MyBaseClass\n    {\n        public MyClass(TS ts)\n        {\n        }\n        public T Hello\u003cTV\u003e(T t, TV tv)\n        {\n            Console.WriteLine(tv);\n            return t;\n        }\n    }\n    */\n\n    var gt = new GtpType(\"T\").SetBaseTypeConstraint(typeof(MyBaseClass));\n\n    var assemblyBuilder = new DynamicAssemblyBuilder(\"MyAssembly\");\n    var typeBuilder = assemblyBuilder.DefineType(\"MyClass\");\n\n    //定义泛型类型参数\n    typeBuilder.DefineGenericParameters(gt, new GtpType(\"TS\"));\n\n    //定义构造函数\n    typeBuilder.DefineConstructor(new Type[] { new GtpType(\"TS\") });\n\n    //定义一个泛型方法，TV不在类中定义，所以属于方法的泛型类型参数\n    var methodBuilder = typeBuilder.DefineMethod(\"Hello\", gt, new Type[] { gt, new GtpType(\"TV\") }, ilCoding: c =\u003e\n    {\n        c.Emitter\n        .ldarg_2.call(typeof(Console).GetMethod(\"WriteLine\", new[] { typeof(object) }))\n        .ldarg_1.ret();\n    });\n\n    var type = typeBuilder.CreateType().MakeGenericType(typeof(MyBaseClass), typeof(int));\n    var obj = Activator.CreateInstance(type, 100);\n\n    var method = type.GetMethod(\"Hello\").MakeGenericMethod(typeof(string));\n    var value = method.Invoke(obj, new object[] { new MyBaseClass(), \"world\" });\n\n    Assert.IsInstanceOfType(value, typeof(MyBaseClass));\n}\n```\n\n### 5、代码编译\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var source = @\"\npublic class TestClass\n{\n    public string Hello(string str)\n    {\n        return str;\n    }\n}\";\n\n    var codeCompilerManager = serviceProvider.GetService\u003cICodeCompilerManager\u003e();\n    var codeCompiler = codeCompilerManager!.CreateCompiler(\"csharp\");\n\n    var opt = new ConfigureOptions();\n    opt.Assemblies.Add(\"System.Core.dll\");\n\n    var assembly = codeCompiler!.CompileAssembly(source, opt);\n\n    var type = assembly!.GetType(\"TestClass\");\n\n    Assert.IsNotNull(type);\n}\n```\n\n　　要使用 `VB.NET` 语言只需要在项目中引用 `Fireasy.CodeCompiler.VisualBasic` 即可。\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var source = @\"\nPublic Class A\n    Public Function Hello(ByVal str As String) As String\n        Return str\n    End Function\nEnd Class\";\n\n    var codeCompilerManager = serviceProvider.GetService\u003cICodeCompilerManager\u003e();\n    var codeCompiler = codeCompilerManager!.CreateCompiler(\"vb\");\n\n    var assembly = codeCompiler!.CompileAssembly(source);\n\n    var type = assembly!.GetType(\"A\");\n\n    Assert.IsNotNull(type);\n}\n```\n\n### 6、对象序列化\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var obj = new TestObject { Name = \"fireasy\", Address = \"kunming\", Age = 30 };\n\n    var serializer = serviceProvider.GetRequiredService\u003cIJsonSerializer\u003e();\n\n    //在明确提供方的情况下，可以指定 JsonSerializerOptions，但是更换提供方后，相应的也要切换\n    var json = serializer.Serialize(obj, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true });\n\n    Console.WriteLine(json);\n}\n```\n\n　　除了 `Json` 序列化，还提供了二进制序列化 `IBinarySerializer`，但目前还没有适配。\n\n### 7、MEF 服务导出\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n\n    var configuration = new ConfigurationBuilder()\n        .SetBasePath(Directory.GetCurrentDirectory())\n        .AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: true)\n        .Build();\n\n    services.AddSingleton\u003cIConfiguration\u003e(configuration);\n\n    var serviceProvider = services.BuildServiceProvider();\n\n    //这是一个扩展方法 GetExportedServices\n    var exportedServices = serviceProvider.GetExportedServices\u003cIExportService\u003e();\n    Assert.AreEqual(2, exportedServices.Count());\n}\n\npublic interface IExportService\n{\n}\n\n[Export(typeof(IExportService))]\npublic class ExportService1 : IExportService\n{\n}\n\n[Export(typeof(IExportService))]\npublic class ExportService2 : IExportService\n{\n}\n```\n\n　　使用配置进行匹配，`assembly` 匹配程序集名称，`pattern` 匹配文件名称。\n\n```json\n{\n  \"fireasy\": {\n    \"imports\": {\n      \"settings\": {\n        \"usePattern\": {\n          \"pattern\": \"Fireasy.*.dll\"\n        },\n        \"useAssembly\": {\n          \"assembly\": \"Fireasy.Composition.Tests\"\n        }\n      }\n    }\n  }\n}\n```\n\n### 8、动态扩展对象\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    //如果不获取 DynamicDescriptionSupporter 则该测试将失败\n    var supporter = serviceProvider.GetService\u003cDynamicDescriptionSupporter\u003e();\n\n    var obj = (IDictionary\u003cstring, object\u003e)new DynamicExpandoObject();\n    obj.Add(\"Name\", \"fireasy\");\n\n    var property = TypeDescriptor.GetProperties(obj).Find(\"Name\", false);\n\n    Assert.IsNotNull(property);\n\n    var value = property.GetValue(obj);\n\n    Assert.AreEqual(\"fireasy\", value);\n}\n```\n\n## 五、数据库类库\n\n　　`IProvider` 定义了一套标准，不同的数据库类型有不同的实现。另外，每种数据库还应实现以下插件服务接口：\n\n* `ISyntaxProvider` 语法插件服务\n\n* `ISchemaProvider` 架构插件服务\n\n* `IBatcherProvider` 批量插入插件服务\n\n* `IRecordWrapper` 记录包装器插件服务\n\n* `IGeneratorProvider` 标识生成器插件服务\n\n　　目前已经提供了 SqlServer、MySql、SQLite、Firebird、PostgreSql、Oracle、Dameng(达梦)、Kingbase(人大金仓)和ShenTong(神通)数据库，以及 OleDb 驱动。\n\n　　Fireasy.Data 中未引用相关的 Nuget 包，只要在项目中直接安装 Nuget 包即可。\n\n| 数据库类型 | Nuget 包 |\n| :-- | :-- |\n| SqlServer | Microsoft.Data.SqlClient、System.Data.SqlClient |\n| MySql | MySql.Data、MySqlConnector |\n| SQLite | System.Data.SQLite、Microsoft.Data.Sqlite |\n| Firebird | FirebirdSql.Data.FirebirdClient |\n| PostgreSql | Npgsql |\n| Oracle | Oracle.ManagedDataAccess |\n| Dameng | DmProvider |\n| Kingbase | Kdbndp |\n| ShenTong | Oscar.Data.SqlClient |\n| OleDb | System.Data.OleDb |\n\n### 1、列举数据库提供者(比如SqlServer、MySql等等)\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n    var serviceProvider = services.BuildServiceProvider();\n\n    var manager = serviceProvider.GetRequiredService\u003cIProviderManager\u003e();\n\n    var descriptors = manager.GetSupportedProviders();\n\n    foreach (var item in descriptors)\n    {\n        Console.WriteLine($\"{item.Alais} {item.Description}\");\n    }\n}\n```\n\n### 2、更换提供者或插件服务\n\n```csharp\nprivate void Test()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n\n    //用于替换 SqlServerProvider 中的 DbProviderFactory\n    builder.ConfigureData(s =\u003e s.AddProivderFactory\u003cSqlServerProvider\u003e(System.Data.SqlClient.SqlClientFactory.Instance));\n\n    //用于替换数据库提供者，SqlServer 不再使用 SqlServerProvider，而是使用自定义的 TestProvider\n    //sqlserver使用2012以下版本的语法\n    builder.ConfigureData(s =\u003e s.AddProvider\u003cTestProvider\u003e(\"SqlServer\").AddProivderService\u003cSqlServerProvider, SqlServerSyntaxLessThan2012\u003e());\n\n    var serviceProvider = services.BuildServiceProvider();\n}\n```\n\n### 3、使用配置文件配置连接字符串\n\n```json\n{\n  \"fireasy\": {\n    \"dataInstances\": {\n      \"default\": \"sqlserver\",\n      \"settings\": {\n        \"sqlite\": {\n          \"providerType\": \"SQLite\",\n          \"connectionString\": \"Data source=|appdir|..\\\\..\\\\..\\\\..\\\\..\\\\..\\\\db\\\\Northwind.db3;Pooling=True\"\n        },\n        \"sqlserver\": {\n          \"providerType\": \"SqlServer\",\n          \"connectionString\": \"Data Source=(LocalDB)\\\\MSSQLLocalDB;AttachDbFilename=|appdir|..\\\\..\\\\..\\\\..\\\\..\\\\..\\\\db\\\\Northwind.mdf;Integrated Security=True;Connect Timeout=30\"\n        },\n        \"oracle\": {\n          \"providerType\": \"Oracle\",\n          \"connectionString\": \"Data Source=localhost/orcl;User ID=c##test;Password=Faib1234\"\n        },\n        \"mysql\": {\n          \"providerType\": \"MySql\",\n          \"connectionString\": \"Data Source=localhost;database=northwind;User Id=root;password=faib;pooling=true;charset=utf8\"\n        },\n        \"oledb_access\": {\n          \"providerType\": \"OleDb\",\n          \"connectionString\": \"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|appdir|..\\\\..\\\\..\\\\..\\\\..\\\\..\\\\db\\\\Northwind.accdb;Persist Security Info=False;\"\n        },\n        \"testdb\": {\n          \"providerType\": \"myprovider\",\n          \"connectionString\": \"Data Source=localhost;database=northwind;User Id=root;password=faib;pooling=true;charset=utf8\"\n        }\n      }\n    },\n    \"dataProviders\": {\n      \"settings\": {\n        \"myprovider\": {\n          \"type\": \"Fireasy.Data.Tests.TestProvider, Fireasy.Data.Tests\"\n        }\n      }\n    }\n  }\n}\n```\n\n### 4、创建数据库实例\n\n```csharp\nprivate async Task TestAsync()\n{\n    var services = new ServiceCollection();\n    var builder = services.AddFireasy();\n\n    var configuration = new ConfigurationBuilder()\n        .SetBasePath(Directory.GetCurrentDirectory())\n        .AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: true)\n        .Build();\n\n    services.AddSingleton\u003cIConfiguration\u003e(configuration);\n\n    var serviceProvider = services.BuildServiceProvider();\n\n    var factory = serviceProvider.GetRequiredService\u003cIDatabaseFactory\u003e();\n\n    //指定提供者及连接串\n    await using var database = factory.CreateDatabase\u003cMySqlProvider\u003e(\"Data Source=localhost;database=northwind;User Id=root;password=faib;pooling=true;charset=utf8\");\n    Assert.IsNotNull(database);\n\n    //指定数据库配置名称\n    await using var database = factory.CreateDatabase(\"oledb_access\");\n    Assert.IsNotNull(database);\n}\n```\n\n### 5、数据库增删改查\n\n```csharp\nprivate async Task TestAsync()\n{\n    //略去 serviceProvider 的创建，见第4节\n\n    var factory = serviceProvider.GetRequiredService\u003cIDatabaseFactory\u003e();\n\n    await using var database = factory.CreateDatabase(\"mysql\");\n\n    //查询列表，带分页\n    var pager = new DataPager(10, 1);\n    var list = await database.ExecuteEnumerableAsync\u003cCustomers\u003e($\"select * from customers order by CustomerID\", pager);\n\n    //单一字段\n    var value = await database.ExecuteScalarAsync\u003cbyte[]\u003e($\"select Picture from categories where CategoryID=1\");\n\n    //更新字段，参数化\n    var parameters = new ParameterCollection();\n    parameters.Add(\"customerId\", \"ALFKI\");\n    parameters.Add(\"country\", \"Germany\");\n    var ret = await database.ExecuteNonQueryAsync($\"update customers set Country=@country where CustomerID=@customerId\", parameters: parameters);\n}\n```\n\n### 6、使用事务\n\n```csharp\nprivate async Task TestAsync()\n{\n    //略去 serviceProvider 的创建，见第4节\n\n    var factory = serviceProvider.GetRequiredService\u003cIDatabaseFactory\u003e();\n\n    await using var database = factory.CreateDatabase(\"mysql\");\n    await database.BeginTransactionAsync();\n\n    try\n    {\n        await database.ExecuteNonQueryAsync($\"delete from customers\");\n        //表不存在，将抛错\n        await database.ExecuteNonQueryAsync($\"delete from testtable\");\n\n        await database.CommitTransactionAsync();\n    }\n    catch (Exception)\n    {\n        await database.RollbackTransactionAsync();\n    }\n}\n```\n\n### 7、获取数据库架构\n\n```csharp\nprivate async Task TestAsync()\n{\n    //略去 serviceProvider 的创建，见第4节\n\n    var factory = ServiceProvider.GetRequiredService\u003cIDatabaseFactory\u003e();\n\n    await using var database = factory.CreateDatabase(\"mysql\");\n    var schema = database.GetService\u003cISchemaProvider\u003e();\n    var syntax = database.GetService\u003cISyntaxProvider\u003e();\n\n    //获取表\n    var tables = await schema!.GetSchemasAsync\u003cData.Schema.Table\u003e(database).ToListAsync();\n\n    var names = new[]\n    {\n        syntax!.ToggleCase(\"products\"),\n        syntax!.ToggleCase(\"customers\"),\n        syntax!.ToggleCase(\"orders\")\n    };\n\n    //多表匹配\n    tables = await schema!.GetSchemasAsync\u003cData.Schema.Table\u003e(database, s =\u003e names.Contains(s.Name)).ToListAsync();\n\n    //获取字段\n    var columns = await schema!.GetSchemasAsync\u003cData.Schema.Column\u003e(database, s =\u003e s.TableName == syntax!.ToggleCase(\"products\") \u0026\u0026 s.Name == \"ProductID\").ToListAsync();\n\n    //获取外键\n    var foreignKeys = await schema!.GetSchemasAsync\u003cData.Schema.ForeignKey\u003e(database, s =\u003e s.TableName.Equals(syntax!.ToggleCase(\"orders\"))).ToListAsync();\n}\n```\n\n### 8、批量插入\n\n```csharp\nprivate async Task TestAsync()\n{\n    //略去 serviceProvider 的创建，见第4节\n\n    var factory = ServiceProvider.GetRequiredService\u003cIDatabaseFactory\u003e();\n\n    await using var database = factory.CreateDatabase(\"mysql\");\n    var batcher = database.GetService\u003cIBatcherProvider\u003e();\n\n    var list = new List\u003cBatcherData\u003e();\n\n    for (var i = 0; i \u003c 100000; i++)\n    {\n        list.Add(new BatcherData(i + 1, \"Name\" + i, \"Address\" + i));\n    }\n\n    await batcher.InsertAsync(database, list, \"batchers\");\n}\n\nprivate class BatcherData\n{\n    public BatcherData(int id, string name, string address)\n    {\n        Id = id;\n        Name = name;\n        Address = address;\n    }\n\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public string Address { get; set; }\n}\n```\n\n## 技术揭秘系列文章\n- [Fireasy3 揭秘 -- 依赖注入与服务发现](https://www.cnblogs.com/fireasy/p/17170417.html)\n- [Fireasy3 揭秘 -- 自动服务部署](https://www.cnblogs.com/fireasy/p/17173997.html)\n- [Fireasy3 揭秘 -- 使用 SourceGeneraor 改进服务发现](https://www.cnblogs.com/fireasy/p/17174121.html)\n- [Fireasy3 揭秘 -- 使用 SourceGeneraor 实现动态代理(AOP)](https://www.cnblogs.com/fireasy/p/17179651.html)\n- [Fireasy3 揭秘 -- 使用 Emit 构建程序集](https://www.cnblogs.com/fireasy/p/17201880.html)\n- [Fireasy3 揭秘 -- 代码编译器及适配器](https://www.cnblogs.com/fireasy/p/17213296.html)\n- Fireasy3 揭秘 -- 使用缓存提高反射性能\n- Fireasy3 揭秘 -- 动态类型及扩展支持\n- Fireasy3 揭秘 -- 线程数据共享的实现\n- Fireasy3 揭秘 -- 配置管理及解析处理\n- Fireasy3 揭秘 -- 数据库适配器\n- Fireasy3 揭秘 -- 解决数据库之间的语法差异\n- Fireasy3 揭秘 -- 获取数据库的架构信息\n- Fireasy3 揭秘 -- 数据批量插入的实现\n- Fireasy3 揭秘 -- 使用包装器对数据读取进行兼容\n- Fireasy3 揭秘 -- 数据行映射器\n- Fireasy3 揭秘 -- 数据转换器的实现\n- Fireasy3 揭秘 -- 通用序列生成器和雪花生成器的实现\n- Fireasy3 揭秘 -- 命令拦截器的实现\n- Fireasy3 揭秘 -- 数据库主从同步的实现\n- Fireasy3 揭秘 -- 大数据分页的策略\n- Fireasy3 揭秘 -- 数据按需更新及生成实体代理类\n- Fireasy3 揭秘 -- 用对象池技术管理上下文\n- Fireasy3 揭秘 -- Lambda 表达式解析的原理\n- Fireasy3 揭秘 -- 扩展选择的实现\n- Fireasy3 揭秘 -- 按需加载与惰性加载的区别与实现\n- Fireasy3 揭秘 -- 自定义函数的解析与绑定\n- Fireasy3 揭秘 -- 与 MongoDB 进行适配\n- Fireasy3 揭秘 -- 模块化的实现原理","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaib920%2Ffireasy3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffaib920%2Ffireasy3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaib920%2Ffireasy3/lists"}