"EF in Enterprise"에 대한 Juile Lerman의 복수형 과정에 정말 감명 받았고 데모 응용 프로그램을 구축하기로 결정했습니다.SOLID 원칙을 적용 할 때 도움이 필요합니다
VS 2012와 최신 버전의 EF, SQL Server 및 MVC를 사용하고 있습니다. 솔리드 (SOLID) 원칙을 적용하는 데모 애플리케이션을 제작 중입니다. DI & 단위 테스트를 구현하는 방법을 더 잘 이해하기 위해이 작업을 수행하고 있습니다.
저는이 데모 응용 프로그램에 대해 DB 첫 번째 접근 방식을 사용했습니다. 여기에는 UserDetails라는 하나의 테이블 만 포함되며 SQL 서버에서 어떻게 보이는지 아래에 나와 있습니다. 이 테이블을 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 응용 프로그램이 될 것입니다. 여기서는 단순히 DB에 쿼리하고 데이터를 표시합니다. 이것은 코드가 어떻게 보이는지입니다.
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와 그것을 교환 할 수 있어야하는 그런 방식으로이 프로젝트에서 그것을 사용하고 싶다. 어떻게 이것을 달성합니까?
이 큰 질문을 읽어 주셔서 감사합니다. 누군가 올바른 방향으로 나를 가리킬 수 있다면 정말 고마워요.
'IRepository'는'IQueryable' 타입을 반환 할 필요가 없습니다. 제발, [이 링크를 참조하십시오] (https://stackoverflow.com/questions/33755499/entity-framework-repository-pattern-why-not-return-iqueryable) – StepUp