ASP.Net MVC和实体框架项目架构没有存储库模式

RuS*_*uSh 4 c# asp.net asp.net-mvc entity-framework linq-to-sql

我正在使用ASP.NET MVC和Entity Framework开始一个新的小项目.(SQL Server - 大约20个DB表)在过去的项目中我使用过Linq2SQL,但它似乎已经过时了.

我已经阅读了很多关于使用EF存储库模式的帖子(优点和缺点),对我而言,没有存储库模式的代码似乎更好/更简单.

我创建了以下项目架构:

namespace MySite.Models
{
    public class User
    {
        public Int32 ID { get; set; }
        public String Email { get; set; }
        public String Password { get; set; }
        public String Name { get; set; }
        public Int32 Gender { get; set; }
    }
}

namespace MySite.DAL
{
    public class Users
    {
       public static IEnumerable<User> GetUsers()
        {
            using (var context = new DatingSiteContext())
            {
                return context.Users.ToList();
            }
        }

        public static User GetUserByID(int id)
        {
            using (var context = new DatingSiteContext())
            {
                return context.Users.Find(id);
            }
        }
}

namespace MySite.Controllers
{
    public class HomeController : Controller
    {

        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            var users = DAL.Users.GetUsers();

            return View(users);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 使用这样的EF有什么缺点?(除了缺乏单元测试支持)
  • 在每次调用DAL时创建一个新的DbContext是错误的吗?任何表现命中?
  • 使用EF的任何其他推荐结构?例子?:)
  • 你会在一个新项目中使用Linq2SQL吗?

谢谢.

编辑:

GetUsers()和GetUserByID()中的代码只是例如,我理解从db返回所有记录的错误做法(缺少分页或过滤器)

Hen*_*ema 7

你实际上只创建了一个存储库,你只称它为"数据访问层",在我看来,这不是一个好名字,因为Entity Framework是数据访问层.在这种情况下,存储库是数据访问层(实体框架)之上的抽象.


在每次调用DAL时创建一个新的DbContext是错误的吗?任何表现命中?

不,这很好,但是当你在一个实例中获取一个实体时,它可能会造成麻烦DbContext,并尝试在另一个实例中更新它.


你会在一个新项目中使用Linq2SQL吗?

不,微软提出实体框架作为L2SQL的继承者,并且它的积极开发已经停止.


使用EF的任何其他推荐结构?例子?:)

您使用的方法,特定的存储库,将导致大量冗余代码.您可以创建实现接口的通用存储库:

public interface IRepository<TEntity> 
    where TEntity : class, new()
{
    IEnumerable<TEntity> GetAll();

    TEntity GetById(int id);

    IQueryable<TEntity> Table { get; }
}
Run Code Online (Sandbox Code Playgroud)

并执行此:

public EfRepository<TEntity> : IRepository<TEntity>
    where TEntity : class, new()
{
    private readonly DatingSiteContext _context;

    public EfRepository()
    {
        _context = new DatingSiteContext();
    }

    private IDbSet<TEntity> Entities
    {
        get
        {
            return _context.Set<TEntity>();
        }
    }

    public IEnumerable<TEntity> GetAll()
    {
        return Entities.ToList();
    }

    public TEntity GetById(int id)
    {
        return Entities.Find(id);
    }

    public IQueryable<TEntity> Table 
    { 
        get { return Entities; }
    }   
}
Run Code Online (Sandbox Code Playgroud)

您可以在控制器中使用此存储库,如下所示:

public class HomeController : Controller
{
    private readonly IRepository<User> _userRepository;

    public HomeController()
    {
        _userRepository = new EfRepository<User>();
    }

    public ActionResult Index()
    {
        var users = _userRepository.GetAll();
        var inactiveUsers = _userRepository.Table.Where(u => !u.Active).ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

此通用存储库允许您创建模拟存储库:

public class FakeUserRepository : IRepository<User> 
{ 
    // ... 
}
Run Code Online (Sandbox Code Playgroud)


这种方法可能看起来像很多代码,但随着实体类型数量的增长,它将为您节省大量工作,因为您所要做的就是IRepository<>在控制器中创建一个字段.然而,您对该IQueryable<>属性具有很大的灵活性,允许延迟执行.

我不是说这是最好的方法,只是我经常在项目中使用的方法.我不得不说我通常在控制器和存储库之间编写一个业务(服务)层.我保留了我的业务逻辑和复杂的Linq查询(及其执行).我还使用一个IoC容器来处理我的对象的生命周期(例如,实例DbContext和服务).有关详细信息,请参阅此问题.