ASP.NET Core 1.0 MVCにはかなり新しいので、MVC Coreアプリにリポジトリパターンを使用することにしました。データ層SampleDbContext
にSQL DBを使用していますが、ビジネスエンティティの一部にRepositoryクラスが必要です。これまでのところ、サンプルエンティティが「Customer」であるstartup.cs
、CustomerController.cs
、およびCustomerRepository.cs
ファイルで以下を実行しました。
スタートアップクラスのConfigureServices
メソッドで:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SampleDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SampleDB")));
}
コントローラー内:
public class CustomerController : Controller
{
private SampleDBContext _context;
private CustomerRepository = new CustomerRepository (new SampleDBContext());
public CustomerController(SampleDBContext context)
{
_context = context;
}
}
リポジトリ内:
public class CustomerRepository
{
private SampleDBContext _context;
public CustomerRepository(SampleDBContext context)
{
_context = context;
}
}
この設計では、SampleDbContext
をstartup.cs
のサービスとして一度プラグインし、その後、各コントローラー(依存性注入を受け取る)に対して、SampleDbContext
の新しいインスタンスに沿って対応するリポジトリーをインスタンス化します。このDBコンテキストの反復的なインスタンス化は、マルチユーザー環境に適した設計ですか?各リポジトリをstartup.cs
にサービスとして追加できると思いますが、見た目は良くありません。私のケースに適した設計の実装を教えてください、または私が失われた場合は正しい軌道に乗せてください。
単純な例 リポジトリパターンの使用方法を見ることができます。
リポジトリインターフェイスを作成します。
using System.Collections.Generic;
namespace TodoApi.Models
{
public interface ITodoRepository
{
void Add(TodoItem item);
IEnumerable<TodoItem> GetAll();
TodoItem Find(long key);
void Remove(long key);
void Update(TodoItem item);
}
}
それを実装します:
using System;
using System.Collections.Generic;
using System.Linq;
namespace TodoApi.Models
{
public class TodoRepository : ITodoRepository
{
private readonly TodoContext _context;
public TodoRepository(TodoContext context)
{
_context = context;
Add(new TodoItem { Name = "Item1" });
}
public IEnumerable<TodoItem> GetAll()
{
return _context.TodoItems.ToList();
}
public void Add(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();
}
public TodoItem Find(long key)
{
return _context.TodoItems.FirstOrDefault(t => t.Key == key);
}
public void Remove(long key)
{
var entity = _context.TodoItems.First(t => t.Key == key);
_context.TodoItems.Remove(entity);
_context.SaveChanges();
}
public void Update(TodoItem item)
{
_context.TodoItems.Update(item);
_context.SaveChanges();
}
}
}
次に、ConfigureServicesに登録します。
services.AddSingleton<ITodoRepository, TodoRepository>();
次に、コントローラーに注入します。
namespace TodoApi.Controllers
{
[Route("api/[controller]")]
public class TodoController : Controller
{
public TodoController(ITodoRepository todoItems)
{
TodoItems = todoItems;
}
public ITodoRepository TodoItems { get; set; }
}
}
DbContext自体がリポジトリパターンであると主張する人もいます。そのルートに進みたい場合は、サンプルコードを ASP.NET Core and Angular 2 からダウンロードできます。
たとえば-
public class CustomerController : Controller
{
private SampleDBContext _context;
public CustomerController(SampleDBContext context)
{
_context = context;
}
public async Task<IActionResult> Index(int id)
{
var user = _context.Users.Where(i => i.Id == id).FirstOrDefault();
...
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SampleDBContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])
);
}
その最善の方法はわかりませんが、私は常に、コントローラーが実装するインターフェースとしてリポジトリを作成しました。
IRepository.cs:
public interface IRepository
{
SomeList GetSomeList(string userId);
Some GetSomeDetail(int someId);
}
DbInterface.cs:
public class DbInterface : IRepository
{
public SomeList GetSomeList(string userId)
{
}
public Some GetSomeDetail(int someId)
{
}
}
SomeListは、ページとしてリストとして表示されるすべてのプロパティで定義したデータ型です。つまりタスクアプリ内のタスクのリスト。 a taskの詳細を返す定義済みのデータ型もあります(そのため、入力はtaskIdなどになります)。
これが悪い方法であるならば、修正されるのは幸せです。