.NET Core多层项目依赖、DI及模型转换问题咨询
问题解答
1. 类库中的依赖注入与DbContext管理
完全可以在类库中使用ASP.NET Core的依赖注入(DI)服务,而且优先推荐用DI管理DbContext的生命周期,而非手动using:
- DI的Scoped生命周期刚好匹配Web请求的周期,ASP.NET Core会自动在请求开始时创建DbContext实例,请求结束时释放,避免手动管理资源的疏漏(比如数据库连接未释放)。
- 类库中使用DI的方式很简单:在类的构造函数中声明依赖的服务(比如DbContext、Provider层的服务),然后在后续的
MyApplication.Web.UI项目的Program.cs中统一注册所有类库的服务和DbContext。
示例代码:// MyApplication.Provider中的类,通过构造函数注入DbContext public class UserProvider { private readonly AppDbContext _dbContext; public UserProvider(AppDbContext dbContext) { _dbContext = dbContext; } // 业务查询方法 } // Web项目Program.cs中注册服务 builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("Default"))); builder.Services.AddScoped<IUserProvider, UserProvider>(); builder.Services.AddScoped<IUserService, UserService>(); - 如果手动用
using创建DbContext,会跳过DI的生命周期管理,容易出现连接池耗尽、事务管理混乱等问题,仅在非Web的独立程序场景可能需要考虑,Web项目下不推荐。
2. Service层转换模型而不依赖DataAccess项目
可以通过依赖倒置原则或中间映射层实现解耦,这里提供两种实用方案:
方案一:引入抽象契约层
- 创建独立类库
MyApplication.Contracts,定义Service层需要的数据接口/抽象模型:// MyApplication.Contracts/IUserDto.cs public interface IUserDto { int Id { get; set; } string Name { get; set; } } MyApplication.DataAccess项目引用Contracts,让实体类实现该接口:// MyApplication.DataAccess/User.cs public class User : IUserDto { public int Id { get; set; } public string Name { get; set; } // 其他数据库字段 }MyApplication.Service项目只引用Contracts和ViewModel,通过接口接收DataAccess传递的数据,再转换为ViewModel:
这样Service层只依赖抽象契约,不直接依赖DataAccess的具体实体。// MyApplication.Service/UserService.cs public class UserService { private readonly IUserProvider _userProvider; public UserService(IUserProvider userProvider) { _userProvider = userProvider; } public UserViewModel GetUser(int id) { IUserDto userDto = _userProvider.GetUserById(id); return new UserViewModel { Id = userDto.Id, DisplayName = userDto.Name }; } }
方案二:独立映射层
- 创建
MyApplication.Mapper类库,该项目同时引用MyApplication.DataAccess和MyApplication.ViewModel,负责实现实体到ViewModel的映射逻辑:// MyApplication.Mapper/UserMapper.cs public static class UserMapper { public static UserViewModel ToViewModel(this User user) { return new UserViewModel { Id = user.Id, DisplayName = user.Name }; } } MyApplication.Service项目只引用MyApplication.Mapper和MyApplication.ViewModel,Provider层返回的DataAccess实体通过映射器转换:
额外优化:可以让Provider层返回抽象接口类型,进一步隐藏DataAccess的具体实体,避免Service层间接依赖。// MyApplication.Service/UserService.cs public UserViewModel GetUser(int id) { var user = _userProvider.GetUserById(id); return user.ToViewModel(); }
内容的提问来源于stack exchange,提问作者M. Kel
相关产品推荐
相关产品推荐

