Я работаю над личным проектом в ядре MVC 2.1, читая о N-уровневых слоях, и применяю следующую схему (я упростил код):
Мой DBContext:
public class CRUDContext : DbContext, IDisposable
{
public CRUDContext(DbContextOptions<CRUDContext> options) : base(options)
{
}
public DbSet<User> User { get; set; }
}
Мой класс (базовый объект имеет поля по умолчанию, такие как ID, createDate и т. Д.)
public class User : BaseEntity
{
public string UserName { get; set; }
}
Startup:
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?}");
});
}
}
Ввод контроллера как DI с другими классами BL:
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
}
МОИ ВОПРОСЫ:
Что лучше?
- Передать контекст через контроллер в BL, поэтому единственный экземпляр
контроллер является пользователем для всего приложения.
- Создайте отдельный DBcontext в каждом BL, чтобы они могли обрабатывать свои
запрос отдельно.
Иногда я получаю эту ошибку:
"Вторая операция была запущена в этом контексте до завершения предыдущей операции. Любые члены экземпляра не гарантированно защищены от потоков." *
Это потому, что я использую тот же контекст БД?
Является ли хорошей идеей использовать методы Async для базовых операций, таких как getById и SelectAll, в моем методе BaseBL?
Надеюсь, я прояснил ситуацию и заранее спасибо ...