Juile Lerman の「EF in Enterprise」に関する複数サイト コースに本当に感銘を受け、デモ アプリを作成することにしました。
VS 2012 と最新バージョンの EF、SQL Server、および MVC を使用しています。SOLID の原則を適用するデモ アプリケーションを構築しています。DIと単体テストの実装方法をよりよく理解するためにこれを行っています。
このデモ アプリケーションでは、DB ファースト アプローチを使用しました。UserDetails という名前のテーブルが 1 つだけ含まれており、以下は 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) 将来、EF を Dapper やその他の ORM ツールと交換したい場合はどうすればよいですか?
d) このプロジェクトに DI ツールをどのように適合させますか? どのレイヤーにあるべきですか?
e) 単体テスト。私は StructureMap を認識しており、将来的に Ninject と交換できるように、このプロジェクトでそれを利用したいと考えています。どうすればこれを達成できますか?
この大きな質問を読んでくれてありがとう。誰かが私を正しい方向に向けることができれば本当に感謝しています。