我正在MVC Core 2.1中从事个人项目,阅读有关N层的信息,我采用以下模式(简化了代码):
我的DBContext:
public class CRUDContext : DbContext, IDisposable
{
public CRUDContext(DbContextOptions<CRUDContext> options) : base(options)
{
}
public DbSet<User> User { get; set; }
}
我的班级(基本实体具有ID,createdDate等默认字段)
public class User : BaseEntity
{
public string UserName { get; set; }
}
启动:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddScoped<EmailBL>();
services.AddScoped<UserBL>();
services.AddScoped<UserTypeBL>();
services.AddScoped<StateBL>();
services.AddScoped<TowerBL>();
services.AddScoped<ResourceBL>();
services.AddScoped<PropertyBL>();
services.AddScoped<NewBL>();
services.AddScoped<ReservationBL>();
services.AddScoped<AmenityBL>();
services.AddScoped<ServiceBL>();
services.AddScoped<ServiceTypeBL>();
services.AddScoped<NewTypeBL>();
services.AddScoped<AccountBL>();
services.AddOptions();
services.AddPaging();
services.AddDbContext<CRUDContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = new PathString("/Account/login");
options.AccessDeniedPath = new PathString("/Account/Denied");
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
env.ConfigureNLog("nlog.config");
loggerFactory.AddNLog();
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
控制器与其他BL类一起作为DI注入:
protected readonly UserBL _userBL;
protected readonly StateBL _stateBL;
protected readonly UserTypeBL _userTypeBL;
public UsersController(UserBL userBL,StateBL stateBL,UserTypeBL userTypeBL)
{
_userBL = userBL;
_stateBL = stateBL;
_userTypeBL = userTypeBL;
}
在我的BL中,它创建一个baseBL的实例
public class UserBL : BaseBL<User>
{
#region Contructor
private readonly CRUDContext _context;
public UserBL(CRUDContext context, ILogger<User> logger = null) : base(context)
{
_context = context;
}
#endregion
#region Metodos Locales
public async Task<bool> UserExistsAsync(String UserName)
{
try
{
return !await _context.User.AnyAsync(e => e.UserName == UserName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error UserExistsAsync");
return false;
}
}
}
在我的BaseBL中,我具有所有基本操作,例如selectable,getbyID,因此仅在业务逻辑必要时才覆盖。
我的BaseBL的一部分
public abstract class BaseBL<T> : DbContext
where T : BaseEntity, new()
{
#region Contructor
private readonly CRUDContext _context;
protected readonly ILogger<T> _logger;
private DbSet<T> _dbSet;
public BaseBL(CRUDContext context, ILogger<T> logger = null)
{
_context = context;
_dbSet = _context.Set<T>();
_logger = logger;
}
#endregion
#region Select All
public virtual IQueryable<T> SelectAll()
{
try
{
return Include(_dbSet.Where(x => x.Status == 1).OrderByDescending(x => x.CreatedDate));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error SelectAll");
return null;
}
}
#endregion
}
我的问题:
哪个更好?
有时我会收到此错误: “在上一个操作完成之前,第二个操作是在此上下文上开始的。不保证任何实例成员都是线程安全的。” 是因为我使用的是相同的数据库上下文?
在我的BaseBL方法中使用异步方法进行诸如getById和SelectAll之类的基本操作是一个好主意吗?
我希望我能说清楚,并预先感谢...