首页 文章

ASP.NET 5 / ASP.NET Core 1中关注点和n层架构的分离

提问于
浏览
21

由于我想使用新的内置依赖注入,我很难找到一种优雅的方法来保持我的DAL层与ASP.NET 5中的MVC / UI层分开 .

例如,我有一个ASP.NET 5项目,一个业务层项目和一个数据访问项目,其中我有各种实体框架代码,如实体和上下文 . 在ASP.NET 5中设置上下文并定位数据库主要文档建议我在StartUp.cs类中执行类似的操作

services.AddEntityFramework()
    .AddSqlServer()
    .AddDbContext<BookContext>(options =>
    {
        options.UseSqlServer(Configuration.Get("Data:ConnectionString"));
    });

这意味着我现在必须在基本上我的UI层中引用我的DAL,根据各种专家和博客文章,多年来一直是不好的做法 .

我解决这个问题的一种方法是创建两个新项目,一个是CompositeRoot项目,它包含生成业务类的工厂类,然后访问DAL,还有一个带有Configuration类的Utilities项目,其中包含 ConnectionString 属性可以传入我的上下文,然后我使用内置的DI来连接所有内容并避免在我的UI层中引用我的DAL . 但我似乎可以在上下文的构造函数或可重写的 OnConfiguration 方法中指定连接字符串 . 另外,到目前为止,所有文档都没有直接在UI中引用DAL类这样的东西吗?或者是否有一种模式,人们正在使用这种新的内置DI /配置为ASP.NET 5保持SOLID?

8 回答

  • 1

    如果您要求10位民用建筑师为您建造一座桥梁,您最终将拥有10种不同的架构 . 没有一个会是相同的,没有一个会比另一个更好 .

    无论他们应用了多少最佳实践和设计模式,每个架构师都会证明他们的想法是正确的 . 有些人会过于热心,有些则会保持简单并完成工作 . 除此之外,预算,交付日期和工艺将对您决定的建筑类型产生直接影响 .

    同样的规则适用于软件架构师 .

    我已经看到了我在世界上拥有最佳意图的建筑师的公平份额,只是意识到UI层依赖于DAL . 也许这背后的原因是:

    • 他们没有想到它

    • 他们并不真正关心它

    • 它有助于DI,因为您可以看到每个层,从而可以轻松地将接口映射到其实现 .

    回到MVC 5,我有以下几层:

    -Contoso.Core (Class Library)
    -Contoso.Data (Class Library)
    -Contoso.Service (Class Library)
    -Contoso.Web (asp.net MVC 5)
    -Contoso.Web.Configuration (Class Library)
    

    Web.Configuration 图层依赖于 CoreDataService . 这层是我配置我的DI东西的地方 .

    Web 图层没有依赖 Data 图层并且启动了东西,我使用的是Bootstrapper Nuget Package .

    也许你可以用ASP.NET 5实现类似的功能

    我希望微软(或任何人)能够创建一个工作项目模板,该模板更适合企业级样本,使用解耦方法甚至像Onion Architecture样本 .

    最后,无论我认为合理的解耦架构对某些人来说可能过多,而对其他人来说则不够......

    随意分享您的发现,因为我很想知道您是如何使其成功的 .

  • -1

    这真的是一个主要问题吗?

    您的UI层将依赖于您的数据层,并且某处会有一些引用 .

    StartUp.cs添加了各种服务和配置,因此大多数这些引用都在一个地方 .

  • 9

    你可以使用Service Locator解决这个问题 .

    例如,您的root / core / abstractions项目中有一个接口:

    public interface IServiceConfiguration
    {
        void ConfigureServices(IServiceCollection services, IConfigurationRoot configuration);
    }
    

    在StartUp.cs中,找到实现IServiceConfiguration的所有类型,并使用它来注册外部服务 .

    public void ConfigureServices(IServiceCollection services)
    {
        var currentAssembly = typeof(Startup).Assembly;
    
        // Limit to project assemblies
        var @namespace = currentAssembly.FullName.Split(',')[0].Split('.')[0];
        var assemblies = currentAssembly.GetReferencedAssemblies()
                                .Where(a => a.Name.StartsWith(@namespace, StringComparison.Ordinal))
                                .Select(a => Assembly.Load(a));
    
        foreach (var assembly in assemblies)
        {
            // Assembly.ExportedTypes is not supported in dnxcore50 so you need to take it off your frameworks node in project.json.
            foreach (var config in assembly.ExportedTypes.Where(t => typeof(IServiceConfiguration).IsAssignableFrom(t) && !t.IsAbstract))
            {
                ((IServiceConfiguration)Activator.CreateInstance(config)).ConfigureServices(services, Configuration);
            }
        }
    
        // More service registrations..
    }
    

    在您的DAL中,您可以添加一个将注册EF的类:

    public sealed class EntityFrameworkServiceConfiguration : IServiceConfiguration
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEntityFramework()
                        .AddSqlServer()
                        .AddDbContext<BookContext>(options =>
                        {
                            options.UseSqlServer(Configuration.Get("Data:ConnectionString"));
                        });
        }
    }
    

    不是每个人都需要这种类型的解耦 . 在某些方面,在StartUp.cs中注册所有内容更有意义 . 无论如何,您都会在Web项目中引用您的DAL(除非所有内容都是通过动态发现),这意味着它已经了解了您的DAL .

  • 0

    我在上面评论过,但我认为很多人可能会有同样的问题 .
    enter image description here

    添加全新的ClassLibraryPackage

    编辑project.json文件

    {
      "version": "1.0.0-*",
      "description": ":)",
      "authors": [ "JJVC" ],
      "tags": [ "" ],
      "projectUrl": "JJVCblog.com",
      "licenseUrl": "",
    
      "frameworks": {
        "dnx451": {
          "frameworkAssemblies": {
          },
          "dependencies": {
            "EntityFramework.Commands": "7.0.0-rc1-final"
          }
        }
      },
    
      "commands": {
        "ef": "EntityFramework.Commands"
      },
    
      "dependencies": {
        "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
        "Microsoft.AspNet.Identity": "3.0.0-rc1-final",
        "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final"
      }
    }
    

    先做你的代码

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole,string>
            {
    
                protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
                {
    
                    optionsBuilder.UseSqlServer(@"server=localhost;Database=Whatever;Integrated Security=True;MultipleActiveResultSets=True;Connect Timeout=60;");
                }
                DbSet<ForgotPasswordResetHistory> ForgotPasswordResetHistory { get; set; }
    
                protected override void OnModelCreating(ModelBuilder builder)
                {
    
                    base.OnModelCreating(builder);
                    base.OnModelCreating(builder);
    
                }
    
    
    
            }
     public class ForgotPasswordResetHistory
        {
            [Key]
            public int ForgotPasswordResetHistoryId { get; set; }
            public bool UserTriedToResetPassword { get; set; }
            public DateTime LinkExpirationDate { get; set; }
            public string SecretCodeForTheLink { get; set; }
            public DateTime PasswordRecoveryRequestDate { get; set; }
            public ApplicationUser ApplicationUser { get; set; }
            public int Test { get; set; }
        }
    

    在文件夹的上下文中启动cmd提示符 . dnu恢复dnx ef migration anyurmigrationname是dnx ed database update

    现在转到您的“web”项目并引用您的数据库 . 在您的Web项目“project.json”中,您应该看到它在依赖项下调用 .

    "ConsoleApp2.Database": "1.0.0-*"
    

    祝好运!

  • 3

    我今天在为MVC 6制作演示时遇到了同样的问题 . 经过一些研究/试验和错误,当我删除

    “EntityFramework.SqlServer”:“7.0.0-beta8”

    project.json 文件一切正常我 .

  • 0

    我最近参加了2016 Global Azure Bootcamp,我们所处理的示例项目(纯粹来自Azure的角度)非常清楚地表达了这些关注点 . 我没有花很多时间来剖析项目,但是如果有人想看,看看这是否适合N-Tier分裂,请回复 . 链接是http://opsgilitytraining.blob.core.windows.net/public/modern-cloud-apps-student.zip . 分离的内容如下:

    • Contoso.Apps.SportsLeague.Web Contoso Sports League电子商务应用程序

    • Contoso.Apps.SportsLeague.Admin Contoso体育联盟呼叫中心管理员申请

    • Contoso.Apps.SportsLeague.WorkerRole 处理订单的收据生成

    • Contoso.Apps.SportsLeague.Data 数据层

    • Contoso.Apps.SportsLeague.Offers 用于返回可用产品列表的API

    • Contoso.Apps.PaymentGateway 用于付款处理的API

  • 0

    从UI层引用数据层的原因是因为我们需要在IoC容器中注册DbContext(如果您使用的是EF) .

    您可以使用MEF(管理扩展性框架)来解决此项目/包参考 . 检查.NET Core中MEF的实现,因为它已从以前的.NET Framework更改 .

    在MEF中,您可以按惯例或通过配置执行此操作 .

  • 0

    您可以在业务层和数据访问层中实现IServiceCollection的扩展方法 .

    然后在Web Startup中,您可以调用业务层上的扩展方法,然后再调用数据层上的扩展方法

    所以这段代码可以在数据层扩展中:

    services.AddEntityFramework()
                        .AddSqlServer()
                        .AddDbContext<BookContext>(options =>
                        {
                           options.UseSqlServer(Configuration.Get("Data:ConnectionString"));
                       });
    

    将事物分开并且web只需要在启动文件中使用语句来引用业务层

相关问题