【问题标题】:How to separate code (clean code separation) in ASP.NET MVC 3?如何在 ASP.NET MVC 3 中分离代码(干净的代码分离)?
【发布时间】:2013-01-08 07:15:04
【问题描述】:

我现在只想知道如何使用 EF 在 MVC3 中以正确的方式分离代码

根据我的项目结构。

演示 -> 视图和控制器

领域 --> 模型(业务实体)

数据 --> RepositoryBase、IRepository、ApplicationDbContext

服务 --> 第三方服务(PayPal、SMS)或应用程序服务

ApplicationDbContext 需要模型作为参考。

public sealed class ApplicationDbContext : DbContext
{

    public DbSet<CountryModel> Country { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

1.那么将 DbContext 放在 Data 中好吗?或者我必须把它移到域中?

现在我必须在 Controller 中编写代码

using (ApplicationDbContext db = new ApplicationDbContext())
{
    var countryRepository = new Repository<Country>(db);

    if (ModelState.IsValid)
    {
        countryRepository.insert(country);
        db.SaveChanges();
    }
}

有什么方法可以将此代码块分隔为任何业务层/服务层?

所以我们只需从控制器调用该层并传递特定的业务实体以执行其余操作。

我想做 PL --> BLL --> DLL 方法使用 MVC 3 & EF?

请建议我正确的方法。

【问题讨论】:

    标签: asp.net-mvc-3 entity-framework


    【解决方案1】:

    那么将 DbContext 放在 Data 中好吗?

    是的,它就是它所属的地方。

    现在在控制器中我必须编写代码

    不,您绝对不应该在控制器中编写这样的代码,因为您现在正在使控制器与您正在使用的特定数据访问技术(在您的情况下为 EF)强耦合。更糟糕的是,您将无法单独对控制器进行单元测试。

    我建议您对接口中的实体进行抽象操作(顺便说一下,您在问题中已经提到了它 - IRepository)。现在您的控制器可以将存储库作为依赖项:

    public class CountriesController: Controller
    {
        private readonly IRepository repository;
        public CountriesController(IRepository repository)
        {
            this.repository = repository;
        }
    
        public ActionResult Index(int id)
        {
            Country country = this.repository.Get<Country>(id);
            return View(country);
        }
    
    
        [HttpPost]
        public ActionResult Index(Country country)
        {
            if (ModelState.IsValid)
            {
                this.repository.Insert(country); 
                return RedirectToAction("Success");
            }
    
            return View(country);
        }
    }
    

    现在您所要做的就是配置您喜欢的依赖注入框架,将这个 IRepository 的具体实现注入到控制器构造函数中。在您的情况下,此特定实现可能是某个实现 IRepository 接口并在内部使用 ApplicationDbContext 的类。

    通过这种方式,您可以从控制器中抽象出数据访问逻辑。

    【讨论】:

    • Greate,但是如果我有多个接口,那我该怎么办?假设 ** CountryRepository: IRepository, ICountryRepository ** 那么在 CountryController(IRepository, ICountryRepository) 我必须这样写吗?而在 CountryRepository 我必须编写 ApplicationDbContext 相关代码?
    • IRepository 可以是通用的,如我的示例所示:IRepository&lt;T&gt;。所以你的CountryRepository 可以实现IRepository&lt;Country&gt;,然后你的控制器将采用IRepository&lt;Country&gt;。这就是你所需要的。现在在CountryRepository 实现中,您可以使用ApplicationDbContext
    • 例如CountryRepository的Get方法中:using (ApplicationDbContext db = new ApplicationDbContext()) { return db.Countries.FirstOrDefault(c =&gt; c.CountryId == id); }
    • 能否给出带有 RepositoryBaseCountryRepository 的代码 ApplicationDbContext 示例?如果我必须在 CountryRepository 中实现另一个 ICountryInterface 所以在 CountryController 我必须通过 IReposotory 和 ICountryReposotory 权利!!!
    • 不,您不需要将任何ICountryRepository 传递给控制器​​。没有这样的界面。您需要的所有控制器都是IRepository&lt;Country&gt;。而你的CountryRepository 类实现IRepository&lt;Country&gt;。如果您的控制器需要与其他模型一起使用,您只需传递它们的存储库即可:IRepository&lt;Product&gt;, IRepository&lt;FooBar&gt;, ...
    【解决方案2】:

    您可以在 BLL 中为彼此创建单独的项目,为每个业务实体调用存储库表单创建类,并创建一些您需要的基本功能,例如插入删除查找带参数的选择等

    var country =new Country();//it's class of BLL
    
    if (ModelState.IsValid)
    {
        country.insert(country);
    }
    

    类似的东西

    【讨论】:

      猜你喜欢
      • 2021-10-10
      • 1970-01-01
      • 2017-06-12
      • 2018-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多