Вы должны сделать шаг назад и подумать о том, что должен делать репозиторий. Хранилище используется для извлечения записей, добавления записей и обновления записей. Репозиторий, который вы создали, едва обрабатывает первый случай, обрабатывает второй случай, но не эффективно, и совсем не обрабатывает третий случай.
Большинство универсальных репозиториев имеют интерфейс, аналогичный
public interface IRepository<T> where T : class
{
IQueryable<T> Get();
void Add(T item);
void Delete(T item);
void CommitChanges();
}
Для извлечения записей вы не можете просто вызвать весь набор с помощью AsEnumerable()
, потому что это загрузит каждую запись базы данных для этой таблицы в память. Если вам нужны только пользователи с именем пользователя username1
, вам не нужно загружать каждого пользователя для базы данных, так как это приведет к значительному снижению производительности базы данных и значительному снижению производительности клиента без какой-либо выгоды.
Вместо этого, как вы увидите из интерфейса, который я разместил выше, вы хотите вернуть IQueryable<T>
объект. IQuerable
разрешают любому классу, вызывающему хранилище, использовать Linq и добавлять фильтры к запросу базы данных, и после запуска IQueryable он полностью запускается в базе данных, получая только нужные записи. База данных гораздо лучше сортирует и фильтрует данные, чем ваши системы, поэтому лучше всего делать на БД как можно больше.
Теперь, что касается вставки данных, у вас есть правильная идея, но вы не хотите немедленно вызывать SaveChanges()
. Причина в том, что лучше всего вызывать Savechanges()
после того, как все ваши операции с БД были поставлены в очередь. Например, если вы хотите создать пользователя и его профиль в одном действии, вы не можете использовать свой метод, потому что каждый вызов Insert
будет вызывать вставку данных в базу данных.
Вместо этого вам нужно разделить вызов Savechanges()
на метод CommitChanges
, который я описал выше.
Это также необходимо для обработки данных обновления в вашей базе данных. Чтобы изменить данные сущности, Entity Framework отслеживает все полученные им записи и следит за ними, чтобы увидеть, были ли внесены какие-либо изменения. Тем не менее, вы все равно должны сказать Entity Framework, что нужно отправить все измененные данные в базу данных. Это происходит с вызовом context.SaveChanges()
. Следовательно, вам нужно, чтобы это был отдельный вызов, чтобы вы могли фактически обновлять отредактированные данные, которые ваша текущая реализация не обрабатывает.
Edit:
Ваш комментарий заставил меня осознать еще одну проблему, которую я вижу. Одним из недостатков является то, что вы создаете контекст данных внутри репозитория, и это не хорошо. Вы действительно должны иметь все (или большинство) ваших созданных репозиториев, совместно использующих один и тот же экземпляр вашего контекста данных.
Entity Framework отслеживает, в каком контексте отслеживается объект, и будет исключением, если вы попытаетесь обновить объект в одном контексте с другим. Это может произойти в вашей ситуации, когда вы начинаете редактировать объекты, связанные друг с другом. Это также означает, что ваш SaveChanges()
вызов не является транзакционным, и каждый объект обновляется / добавляется / удаляется в своей собственной транзакции, что может привести к путанице.
Мое решение этого в моих репозиториях заключается в том, что DbContext
передается в репозиторий в конструкторе.