1. Имеет ли значение, что нет четкого различия между BLL и DAL?.
Это точно имеет значение! Любой программист, использующий ваше свойство Table, должен понимать последствия (обратное обращение к базе данных, перевод запросов, отслеживание объектов). Это касается и программистов, читающих классы бизнес-логики.
2. Рассматривается ли возможность запросов к доступу к данным или бизнес-логике, когда за слоем репозитория действует абстракция InMemory?
Абстракция - это одеяло, под которым мы скрываем свои проблемы.
Если ваша абстракция безупречна, то запросы можно абстрактно рассматривать как работающие с коллекциями в памяти, и, следовательно, они не являются доступом к данным.
Тем не менее, утечка абстракций. Если вам нужны запросы, которые имеют смысл в мире данных, необходимо приложить усилия, чтобы работать над абстракцией и за ее пределами. Это дополнительное усилие (которое побеждает абстракцию) создает код доступа к данным.
Некоторые примеры:
output = work.GetRepository<Bar>().Table.ToArray();
Это код (абстрактно) в порядке. Но в мире данных это приводит к сканированию всей таблицы и является (по крайней мере, вообще) глупым!
badquery = work.GetRepository<Customer>().Table.Where(c => c.Name.Contains("Bob")).ToArray();
goodquery = work.GetRepository<Customer>().Table.Where(c => c.Name.StartsWith("Bob")).ToArray();
Goodquery лучше, чем плохой запрос, если есть индекс на Customer.Name
. Но этот факт нам недоступен, пока мы не снимаем абстракцию.
badquery = work.GetRepository<Customer>().Table
.GroupBy(c => c.Orders.Count())
.Select(g => new
{
TheCount = g.Key,
TheCustomers = g.ToList()
}).ToArray();
goodquery = work.GetRepository<Customer>().Table
.Select(c => new {Customer = c, theCount = c.Orders.Count())
.ToArray()
.GroupBy(x => x.theCount)
.Select(g => new
{
TheCount = g.Key,
TheCustomers = g.Select(x => x.Customer).ToList()
})
.ToArray();
goodquery лучше, чем плохой запрос, поскольку badquery будет запрашивать базу данных по групповому ключу для каждой группы (и, что еще хуже, вряд ли найдется индекс, помогающий фильтровать клиентов по c.Orders.Count()
).
Тестируемость встроена в дизайн репозитория. Мы можем использовать реализацию InMemory, чтобы утверждать результаты с ожиданиями.
Не думайте, что ваши запросы проверяются, если вы действительно запускаете их для коллекций в памяти. Эти запросы не проверяются, если не задействована база данных.