Juile Lerman 的“EF in Enterprise”课程给我留下了深刻的印象,并决定构建我的演示应用程序。
我正在使用 VS 2012 和最新版本的 EF、SQL Server 和 MVC。我正在构建一个应用 SOLID 原则的演示应用程序。我这样做是为了更好地了解如何实施 DI 和单元测试。
我在这个演示应用程序中使用了 DB first 方法。它只包含一个名为 UserDetails 的表,下面是它在 SQL Server 中的外观。我将使用此表进行 CRUD 操作。
下面是我如何分层我的应用程序:
1. WESModel 解决方案:这一层包含我的 Model1.edmx 文件和上下文类,如下所示。
namespace WESModel
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using WESDomain;
public partial class WESMVCEntities : DbContext
{
public WESMVCEntities()
: base("name=WESMVCEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<UserDetail> UserDetails { get; set; }
}
}
2. WESDomain 解决方案:这一层包含我的域类(或 POCO 类)。这些 POCO 类实际上是在我的 WESModel 层中自动生成的。我把它们移到这一层。这是单个 POCO 类的外观。
namespace WESDomain
{
using System;
using System.Collections.Generic;
public partial class UserDetail:IUserDetail
{
public int Id { get; set; }
public string UserName { get; set; }
}
}
3:WESDataLayer 解决方案: 这个层包含对我上面2层的dll的引用。这一层有我的存储库类,如下所示。现在,我将 IRepository 保留在同一个类中:)
namespace WESDataLayer
{
public class UserDetailRepository : IUserDetailRepository
{
WESMVCEntities context = new WESMVCEntities();
public IQueryable<IUserDetail> All
{
get { return context.UserDetails; }
}
public IQueryable<IUserDetail> AllIncluding(params Expression<Func<IUserDetail, object>>[] includeProperties)
{
IQueryable<IUserDetail> query = context.UserDetails;
foreach (var includeProperty in includeProperties) {
query = query.Include(includeProperty);
}
return query;
}
public IUserDetail Find(int id)
{
return context.UserDetails.Find(id);
}
public void InsertOrUpdate(UserDetail userdetail)
{
if (userdetail.Id == default(int)) {
// New entity
context.UserDetails.Add(userdetail);
} else {
// Existing entity
context.Entry(userdetail).State = EntityState.Modified;
}
}
public void Delete(int id)
{
var userdetail = context.UserDetails.Find(id);
context.UserDetails.Remove(userdetail);
}
public void Save()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public interface IUserDetailRepository : IDisposable
{
IQueryable<IUserDetail> All { get; }
IQueryable<IUserDetail> AllIncluding(params Expression<Func<UserDetail, object>>[] includeProperties);
UserDetail Find(int id);
void InsertOrUpdate(UserDetail userdetail);
void Delete(int id);
void Save();
}
}
4:ConsoleApplication1 解决方案:这是我的 UI 层。这将是我最终应用程序中的 MVC 应用程序。这里我只是查询数据库并显示数据。这就是代码的外观。
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
IUserDetailRepository repo = new UserDetailRepository();
var count = repo.All.ToList().Count().ToString();
Console.WriteLine("Count: {0}", count);
Console.ReadLine();
}
}
}
问:我的 UI 层没有对 EF DLL 的任何引用。但是,它有一个 Repository 类的实例。在 MVC 应用程序中,我的控制器将具有存储库类或 UnitOfWork 的实例。
a) 这是正确的做法吗?
b)有什么办法可以抽象出来吗?
c) 如果将来我想用 Dapper 或任何其他 ORM 工具替换 EF 怎么办?
d) 我如何在这个项目中安装我的 DI 工具?应该在哪一层?
e) 单元测试。我知道 StructureMap 并希望在这个项目中使用它,以便将来我应该能够将它与 Ninject 交换。我如何做到这一点?
感谢您阅读这个大问题,如果有人能指出我正确的方向,我真的很感激。