.net核心N层中的适当架构

时间:2019-03-22 14:13:59

标签: c# .net design-patterns architecture core

我正在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
}

我的问题:

哪个更好?

  • 通过控制器将上下文传递给BL,因此只有 控制器是整个应用程序的用户。
  • 在每个BL中创建一个单独的DBcontext,以便他们可以处理其 单独请求。

有时我会收到此错误: “在上一个操作完成之前,第二个操作是在此上下文上开始的。不保证任何实例成员都是线程安全的。” 是因为我使用的是相同的数据库上下文?

在我的BaseBL方法中使用异步方法进行诸如getById和SelectAll之类的基本操作是一个好主意吗?

我希望我能说清楚,并预先感谢...

0 个答案:

没有答案
相关问题