具有分层 Web 应用程序的实体框架
Posted
技术标签:
【中文标题】具有分层 Web 应用程序的实体框架【英文标题】:Entity Framework with a layered web application 【发布时间】:2014-02-13 23:56:47 【问题描述】:我知道这个问题似乎已经在这里提出了,但是我有具体的疑问,主要是数据库优先使用,并且在回答的问题中缺少代码示例。
我有这些层:核心、数据和 UI (asp.net mvc)。 我在 MSSQL 中有这些表:Person 和 Contact。
问题 1:在数据层,EDMX 生成 Person 和 Data POCO。我在哪里写像 SearchPersonByCity()
这样的方法?我是否需要在同一数据层中创建另一个 Person 类,仅用于写入数据 CRUD?我怎么做这个?请举个例子(类、命名空间等。不需要整个实际代码)
问题 2:如何在数据层和核心(域模型)之间转换这些数据?我需要在核心(域)类中在哪里创建相同的SearchPersonByCity()
?也许只是为这些数据访问方法在核心层创建另一个 Person 类?
请给我一些代码示例,以及大公司在现实生活中的表现,因为它似乎很愚蠢,需要维护大量代码,并且很可能我出错了。
我并不懒惰,我阅读了数百页的 Entity Framework 书籍,这里有问题,我无法弄清楚如何在代码中做到这一点。
【问题讨论】:
【参考方案1】:在我看来,我会在你的情况下使用存储库模式,所以首先你定义了一个 IRepository 类:
public interface IRepository<T> where T :
void Add(T entity);
void Update(T entity);
void Delete(T entity);
void Delete(Expression<Func<T, bool>> where);
T GetById(long id);
T GetById(string id);
T Get(Expression<Func<T, bool>> where);
还有一个抽象基 RepositoryBase 类:
public abstract class RepositoryBase<T> where T : class
private PersonDBEntities dataContext;
private readonly IDbSet<T> dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
protected IDatabaseFactory DatabaseFactory
get;
private set;
protected PersonDBEntities DataContext
get return dataContext ?? (dataContext = DatabaseFactory.Get());
public virtual void Add(T entity)
dbset.Add(entity);
public virtual void Update(T entity)
dbset.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
public virtual void Delete(T entity)
dbset.Remove(entity);
public virtual void Delete(Expression<Func<T, bool>> where)
IEnumerable<T> objects = dbset.Where<T>(where).AsEnumerable();
foreach (T obj in objects)
dbset.Remove(obj);
public virtual T GetById(long id)
return dbset.Find(id);
public virtual T GetById(string id)
return dbset.Find(id);
public virtual IEnumerable<T> GetAll()
return dbset.ToList();
//You can return IQueryable if you want to build your expression true later on...
public virtual IEnumerable<T> Get(Expression<Func<T, bool>> where)
return dbset.Where(where).ToList();
还有你的 PersonRepository 类:
public class PersonRepository: RepositoryBase<Person>, IPersonRepository
public PersonRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
public interface IPersonRepository : IRepository<Person> // Person will be your POCO class
下一步是在您的服务层上,您将定义并实现实际的 SearchPersonByCity() 方法:
public class PersonService : IPersonService
private readonly IPersonRepository personRepository;
private readonly IUnitOfWork unitOfWork;
public PersonService(IPersonRepository personRepository, IUnitOfWork unitOfWork)
this.personRepository = personRepository;
this.unitOfWork = unitOfWork;
public IEnumerable<Person> SearchPersonByCity(string city)
var persons = personRepository.Get(p => p.City == city);
return persons;
【讨论】:
但有一件事。我的 EDMX 在 Repository 层,对吧?因此,作为您在服务层工作的 POCO Person 类。 UI 层(asp.net mvc)会访问这些 Repository 自动生成的数据实体吗? Repositories 对象将与您的 EDMX 实体模型对象位于同一层。 EDMX 是您的 dbcontext。您的 Repository 基类将包含 dbcontext 的一个实例。您可以将 POCO 类放在域模型层中。 UI 层 (mvc) 只能访问作为包装层的服务层来调用您的存储库方法。 “你可以把你的 POCO 类放在域模型层”怎么样?在您的代码示例中,您将 DATA-MODEL 返回给服务,它会在 UI 中使用 DATA-MODEL,这是错误的。它应该返回域模型或视图模型以在 UI 中工作,对吗?那么,会怎么样呢? 是的,您可以这样做,但在我看来,这有点过度架构。 POCO 类也可以用作您的业务对象。您可能想要添加您的 Person POCO 类的业务对象,并在 SearchPersonByCity 方法中,将 POCO Person 类映射到您的业务 Person 类,改为返回 IEnumerable以上是关于具有分层 Web 应用程序的实体框架的主要内容,如果未能解决你的问题,请参考以下文章