You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于非EF仓储模式的N层架构项目:跨UI统一读取配置需求

嘿,这个学校作业的需求挺明确的,咱们一步步拆解实现,保证满足所有要求:仓储模式、不依赖Entity Framework、N层架构、跨WPF/ASP.NET Core统一读取配置、支持多数据库。

解决方案:无EF的仓储模式N层架构 + 跨UI统一配置读取

一、整体架构分层设计

首先得把各层职责划清楚,核心是让配置读取和数据访问完全脱离UI层,架构分为5层:

  • UI层:WPF(依赖App.config)、ASP.NET Core 2.0网站(依赖appsettings.json)——只负责交互展示,不碰配置和数据逻辑
  • 业务逻辑层(BLL):处理业务规则,依赖仓储层,通过接口调用数据服务
  • 仓储层(Repository):实现数据访问逻辑,基于ADO.NET/Dapper(替代EF),支持多数据库
  • 核心层(Core):提供统一的配置读取接口、数据库连接工厂、通用仓储接口——这是跨UI兼容的关键
  • 实体层(Entities):数据库实体模型,各层共享的纯POCO类

二、跨UI统一配置读取实现

核心思路是:用接口抽象配置读取能力,针对WPF和ASP.NET Core分别实现,再通过依赖注入(DI)让底层层只依赖接口,不关心具体UI的配置源。

1. 定义统一配置接口(Core层)

在Core层创建IAppConfiguration,抽象所有配置读取操作:

public interface IAppConfiguration
{
    // 根据名称获取数据库连接字符串
    string GetConnectionString(string connectionName);
    // 可扩展其他配置项,比如日志级别、缓存超时等
}

2. 针对不同UI框架实现配置读取

(1)WPF端实现(适配App.config)

在WPF项目中创建WpfAppConfiguration,利用ConfigurationManager读取配置:

using System.Configuration;

public class WpfAppConfiguration : IAppConfiguration
{
    public string GetConnectionString(string connectionName)
    {
        return ConfigurationManager.ConnectionStrings[connectionName]?.ConnectionString;
    }
}

(2)ASP.NET Core 2.0端实现(适配appsettings.json)

在ASP.NET Core项目中创建AspNetCoreAppConfiguration,利用框架自带的IConfiguration:

using Microsoft.Extensions.Configuration;

public class AspNetCoreAppConfiguration : IAppConfiguration
{
    private readonly IConfiguration _config;

    public AspNetCoreAppConfiguration(IConfiguration config)
    {
        _config = config;
    }

    public string GetConnectionString(string connectionName)
    {
        return _config.GetConnectionString(connectionName);
    }
}

3. 依赖注入绑定配置实现

在各自UI层启动时,注册对应的配置实现,让底层层能通过接口拿到配置:

  • WPF:用轻量DI容器(比如Autofac),在App.xaml.cs的OnStartup中注册:
var containerBuilder = new ContainerBuilder();
// 注册配置实现为单例
containerBuilder.RegisterType<WpfAppConfiguration>().As<IAppConfiguration>().SingleInstance();
// 同时注册BLL、仓储层的服务
var container = containerBuilder.Build();
// 保存容器供全局使用
  • ASP.NET Core 2.0:在Startup.cs的ConfigureServices中注册:
services.AddSingleton<IAppConfiguration>(provider => 
    new AspNetCoreAppConfiguration(provider.GetRequiredService<IConfiguration>()));
// 注册其他业务、仓储服务

这样一来,BLL和仓储层只需要依赖IAppConfiguration,完全不用关心是WPF还是ASP.NET Core的配置源,彻底实现了解耦。

三、仓储模式与多数据库支持

不用EF的话,推荐用Dapper(轻量ORM,手写SQL灵活,适配多数据库)来实现仓储层。

1. 定义通用仓储接口与连接工厂(Core层)

先定义仓储的通用操作接口:

public interface IRepository<T> where T : class
{
    IEnumerable<T> GetAll();
    T GetById(int id);
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
}

再定义数据库连接工厂,用来创建不同类型的数据库连接:

public interface IDbConnectionFactory
{
    IDbConnection CreateConnection(string connectionName);
}

2. 实现多数据库连接工厂(Core层)

根据配置的连接字符串,判断数据库类型并创建对应连接(需要引用对应数据库的ADO.NET驱动,比如System.Data.SqlClient、MySql.Data.MySqlClient):

public class DbConnectionFactory : IDbConnectionFactory
{
    private readonly IAppConfiguration _config;

    public DbConnectionFactory(IAppConfiguration config)
    {
        _config = config;
    }

    public IDbConnection CreateConnection(string connectionName)
    {
        var connectionString = _config.GetConnectionString(connectionName);
        // 根据连接字符串特征判断数据库类型,也可以在配置里额外指定DbType
        if (connectionString.Contains("SqlServer") || connectionString.Contains("Initial Catalog"))
        {
            return new SqlConnection(connectionString);
        }
        else if (connectionString.Contains("MySql") || connectionString.Contains("Uid"))
        {
            return new MySqlConnection(connectionString);
        }
        throw new NotSupportedException("当前不支持该数据库类型");
    }
}

3. 实现通用仓储基类(仓储层)

封装通用CRUD操作,避免重复代码:

public abstract class BaseRepository<T> : IRepository<T> where T : class
{
    protected readonly IDbConnection _dbConnection;

    public BaseRepository(IDbConnectionFactory connectionFactory, string connectionName)
    {
        _dbConnection = connectionFactory.CreateConnection(connectionName);
        _dbConnection.Open();
    }

    public IEnumerable<T> GetAll()
    {
        // 用Dapper执行查询,表名可根据实体类自定义
        return _dbConnection.Query<T>($"SELECT * FROM {typeof(T).Name}");
    }

    public T GetById(int id)
    {
        return _dbConnection.QueryFirstOrDefault<T>(
            $"SELECT * FROM {typeof(T).Name} WHERE Id = @Id", 
            new { Id = id });
    }

    public void Add(T entity)
    {
        // 实现插入逻辑,可根据实体属性生成SQL,或用Dapper的Insert扩展
        _dbConnection.Execute("INSERT INTO ...", entity);
    }

    // Update、Delete方法类似实现,根据业务需求调整
    public void Update(T entity) { /* ... */ }
    public void Delete(T entity) { /* ... */ }
}

4. 针对特定数据库的仓储实现(可选)

如果某些数据库有特殊SQL语法,可以继承基类重写方法:

public class SqlServerUserRepository : BaseRepository<User>
{
    public SqlServerUserRepository(IDbConnectionFactory connectionFactory) 
        : base(connectionFactory, "SqlServerConnection")
    {
    }

    // 重写GetAll,添加SQL Server特有的NOLOCK优化
    public override IEnumerable<User> GetAll()
    {
        return _dbConnection.Query<User>("SELECT * FROM Users WITH(NOLOCK)");
    }
}

四、配置文件示例

1. WPF的App.config

<configuration>
  <connectionStrings>
    <add name="SqlServerConnection" 
         connectionString="Server=.;Database=SchoolDb;Integrated Security=True" />
    <add name="MySqlConnection" 
         connectionString="Server=localhost;Database=SchoolDb;Uid=root;Pwd=your_password" />
  </connectionStrings>
</configuration>

2. ASP.NET Core 2.0的appsettings.json

{
  "ConnectionStrings": {
    "SqlServerConnection": "Server=.;Database=SchoolDb;Integrated Security=True",
    "MySqlConnection": "Server=localhost;Database=SchoolDb;Uid=root;Pwd=your_password"
  }
}

五、关键注意事项

  • 依赖注入是核心:通过DI注入IAppConfiguration和IDbConnectionFactory,让各层解耦,方便单元测试和扩展新UI框架。
  • SQL兼容性:尽量使用标准SQL,针对不同数据库的特殊语法,通过重写仓储方法来适配。
  • 配置安全:生产环境不要硬编码敏感信息,WPF可以用DPAPI加密配置,ASP.NET Core可以用用户机密或密钥管理服务。

内容的提问来源于stack exchange,提问作者Dvg22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:55:02