DI-Dependency Injection And EF(Entity Framework)

一 理解

    1 设计原则和模式:解耦合代码,降低应用程序代码的耦合度。

       程序易扩展、测试、延迟绑定;

    2  编程思维

       功能性类型喜欢定义成静态类,使用依赖注入,避免使用静态类,使用服务容器管理。

二  依赖注入的过程   

//1 创建服务容器:ServiceCollection
IServiceCollection serviceCollection = new ServiceCollection();

//2 将定义好的类加入容器
serviceCollection.AddSingleton<Fan>();
serviceCollection.AddSingleton<IAppliance, Fan>();
//serviceCollection.AddScoped<Fan>();
//serviceCollection.AddTransient<Fan>();
//3 获取服务提供器
ServiceProvider prv = serviceCollection.BuildServiceProvider();
//4 获取服务
var fanService = prv.GetService<Fan>();
//5 调用服务方法
fanService.turnOn();

 三   DI连同EF(Entity Framework)Console应用程序示例

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting.Internal;
using Microsoft.Extensions.Logging;
using MiniEFConsoleDemo.Data;
using MiniEFConsoleDemo.Services;
using MiniEFConsoleDemo.Settings.Classes;
using MiniEFConsoleDemo.Settings.Services;
using static System.Net.Mime.MediaTypeNames;

Console.WriteLine("Hello, World!");

// 1. 构建配置
var config = new ConfigurationBuilder()
    .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .Build();

//// 2. 注册服务
//var services = new ServiceCollection();

using var host = CreateHostBuilder(args).Build();



/*
// 注册 AppDbContext到依赖注入容器
services.AddDbContext<AppDbContext>(options =>
{   
    options.UseSqlServer(
        config.GetConnectionString("EFDBConnection"),
        b => b.MigrationsAssembly("MiniEFConsoleDemo") // 指定迁移程序集
    );

    // 可选:在控制台输出 SQL 日志
    options.LogTo(Console.WriteLine, LogLevel.Information);
});

// 注册业务服务
services.AddScoped<UserService>();
services.AddScoped<OrderService>();

// 注册配置
var appSet = config.GetSection("AppSettings");
services.Configure<AppSettings>(config.GetSection("AppSettings"));

var environment = new HostingEnvironment
{
    EnvironmentName = "Development",
    ApplicationName = "MyConsoleApp",
    ContentRootPath = Directory.GetCurrentDirectory()
};
services.AddSingleton<IHostEnvironment>(environment);


// 3. 构建服务容器
var serviceProvider = services.BuildServiceProvider();

serviceProvider.GetRequiredService<AppDbContext>();
*/

var serviceProvider = host.Services;


// 4. 自动创建数据库(开发环境使用)或数据库迁移
using (var scope = serviceProvider.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
    var env = scope.ServiceProvider.GetRequiredService<IHostEnvironment>();
    try
    {
        if (env.IsDevelopment())
        {
            await context.Database.EnsureCreatedAsync();
        }
        else
        {
            //回滚到初始状态
            //相当于Update-Database 0
            //await context.Database.MigrateAsync("0");
            //应用所用挂起的迁移文件,如果没有迁移文件不做任何工作
            //相当于 update-database
            await context.Database.MigrateAsync();
            // 应用指定的单个迁移
            //相当于 update-database 20240101000000_InitialCreate
            // await context.Database.MigrateAsync("20240101000000_InitialCreate");

        }
        // 可选:验证数据库连接
        if (await context.Database.CanConnectAsync())
        {
            Console.WriteLine("数据库连接成功");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"数据库初始化失败: {ex.Message}");
        throw;
    }
}

//5.使用服务
using (var scope = serviceProvider.CreateScope())
{
    var userService = scope.ServiceProvider.GetRequiredService<UserService>();
    var orderService = scope.ServiceProvider.GetRequiredService<OrderService>();

    // 创建用户
    var user = await userService.CreateUserAsync("张三", "zhangsan@example.com");
    Console.WriteLine($"创建用户成功: {user.Name}, ID: {user.Id}");

    // 创建订单
    var order = await orderService.CreateOrderAsync(user.Id, 99.99m);
    Console.WriteLine($"创建订单成功: {order.OrderNumber}, 金额: {order.Amount}");

    // 查询所有用户
    var users = await userService.GetAllUsersAsync();
    foreach (var u in users)
    {
        Console.WriteLine($"用户: {u.Name}, 邮箱: {u.Email}, 订单数: {u.Orders?.Count ?? 0}");
    }
}

Console.WriteLine("按任意键退出...");
//Console.ReadKey();

static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                // 配置服务
                var config = new ConfigurationBuilder()
                    .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .Build();
                services.AddDbContext<AppDbContext>(options =>
                {
                    options.UseSqlServer(
                        config.GetConnectionString("EFDBConnection"),
                        b => b.MigrationsAssembly("MiniEFConsoleDemo") // 指定迁移程序集
                    );
                    // 可选:在控制台输出 SQL 日志
                    options.LogTo(Console.WriteLine, LogLevel.Information);
                });

                // 注册业务服务
                services.AddScoped<UserService>();
                services.AddScoped<OrderService>();

                // 注册配置
                var appSet = config.GetSection("AppSettings");
                services.Configure<AppSettings>(config.GetSection("AppSettings"));

                var environment = new HostingEnvironment
                {
                    EnvironmentName = "Development",
                    ApplicationName = "MyConsoleApp",
                    ContentRootPath = Directory.GetCurrentDirectory()
                };
                services.AddSingleton<IHostEnvironment>(environment);

                // 配置选项
                services.Configure<AppSettings>(context.Configuration.GetSection("AppSettings"));
            })
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders();
                logging.AddConsole();
                logging.AddDebug();
                logging.SetMinimumLevel(LogLevel.Information);
            });



// 1 Read appsettings.json file to get the data.
string conStr = DirectReadSettings();

// 2 Bind the appsetings class to get the data.
conStr = BindSettings();

ServiceOption();

static string DirectReadSettings()
{
    string conStr = string.Empty;
    var config = new ConfigurationBuilder()
               .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) // 设置基础路径为程序运行目录
               .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
               .Build();

    // 读取单个值
    conStr = config?.GetConnectionString("EFDBConnection") ?? string.Empty;
    Console.WriteLine($"connectionstring:{conStr}");
    return conStr;
}

static string BindSettings()
{
    string result = string.Empty;
    var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .Build();

    // 方式一:直接绑定
    var appSettings = configuration.GetSection("AppSettings").Get<AppSettings>();
    result = appSettings?.AppName ?? string.Empty;
    Console.WriteLine($"AppSetting  AppName-{appSettings?.AppName ?? string.Empty} AppVersion-{appSettings?.Version ?? string.Empty}");
    return result;
}

static void ServiceOption()
{
    var config = new ConfigurationBuilder()
                  .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) // 设置基础路径为程序运行目录
                  .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                  .Build();
    // 注册服务
    var services = new ServiceCollection();
    services.Configure<AppSettings>(config.GetSection("AppSettings"));

    services.AddSingleton<MyService>();
    // 构建服务
    var serviceProvider = services.BuildServiceProvider();
    // 解析创建服务
    var myService = serviceProvider.GetRequiredService<MyService>();
    serviceProvider.GetService<MyService>();
    myService.Run();
}

 

 

    

posted on 2025-05-21 15:10  博观约取*厚积薄发  阅读(24)  评论(0)    收藏  举报