В проекте, над которым я сейчас работаю, Linq to SQL используется в качестве технологии доступа к данным ORM. Это веб-приложение MVC3. Проблема, с которой я столкнулся, была связана, прежде всего, с невозможностью моделирования (для тестирования) DataContext, который автоматически создается конструктором DBML.
Таким образом, чтобы решить эту проблему (после большого прочтения) я реорганизовал существующую систему репозитория - единый репозиторий с отдельными и дублированными методами доступа для каждой таблицы, который в итоге получил около 300 методов, только 10 из которых были уникальными - в единый репозиторий с универсальными методами, берущими таблицу и возвращающими более универсальные типы в верхние области приложения. DataContext теперь упакован и легко подделан.
[Редактировать: Для этого я использовал ссылку, предоставленную Джейкобом ниже, по совпадению!]
Мой вопрос вращается больше вокруг дизайна, который я использовал до сих пор, и различий, которые я замечаю в структуре приложения.
1) Рефакторинг кода, который использовал классические запросы Linq to SQL:
public Billing GetBilling(int id)
{
var result = (
from bil in _bicDc.Billings
where bil.BillingId == id
select bil).SingleOrDefault();
return (result);
}
теперь это выглядит так:
public T GetRecordWhere<T>(Expression<Func<T, bool>> predicate) where T : class
{
T result;
try
{
result = _dataContext.GetTable<T>().Where(predicate).SingleOrDefault();
}
catch (Exception ex)
{
throw ex;
}
return result;
}
и используется контроллером с запросом в следующих строках:
_repository.GetRecordWhere<Billing>(x => x.BillingId == 1);
что хорошо, и именно то, чего я хотел достичь.
... однако ... Я также должен сделать следующее, чтобы получить именно тот набор результатов, который мне требуется в классе контроллера (высшая точка приложения по существу) ...
viewModel.RecentRequests = _model.GetAllRecordsWhere<Billing>(x => x.BillingId == 1)
.Where(x => x.BillingId == Convert.ToInt32(BillingType.Submitted))
.OrderByDescending(x => x.DateCreated).
Take(5).ToList();
Это - насколько я понимаю, правильно - теперь использует Linq to Objects, а не запросы Linq to SQL, которыми я был ранее? Это хорошая практика? Мне кажется, что это неправильно, но я не знаю почему. Вероятно, потому что логика запросов находится на самом высоком уровне приложения, а не на самом низком, но ... Я обращаюсь к вам, хорошие люди за советом. Одна из проблем, которую я рассмотрел, заключалась в переносе всей таблицы в память, но я понимаю, что при использовании возвращаемого типа Iqeryable предложение where переносится в базу данных и там оценивается. Таким образом, возвращая только тот набор результатов, который мне требуется ... я могу ошибаться.
И если вы сделали это далеко, молодец. Спасибо, и если у вас есть какие-либо советы, это очень ценится!
Обновление: включение метода GetAllRecordsWhere в соответствии с запросом
public IQueryable<T> GetAllRecordsWhere<T>(Expression<Func<T, bool>> predicate) where T : class
{
return _dataContext.GetTable<T>().Where(predicate);
}
, который использует:
public IQueryable<TName> GetTable<TName>() where TName : class
{
return _db.GetTable<TName>().AsQueryable();
}