Тарифы Услуги Сим-карты

CRUD операции со связанными данными

Связи между сущностями в модели - это отражение реляционных связей между таблицами в БД. Реляционные связи в таблицах реализованы через первичные и внешние ключи, связи в модели Entity на основе навигационных свойств сущностей.

В базе нашего проекта 2 таблицы: Tenants и Apartments. Они связаны отношением «один ко многим». Это значит, что в одной квартире могут проживать несколько жильцов, но один жилец может быть жить только в одной квартире.

На уровне кода (в классах модели) навигационные свойства становятся массивами с ссылками на объекты.

Public class Apartment { public int ApartmentID { get; set; } public decimal ApartСost { get; set; } public int Apartnumber { get; set; } public int NumberofRooms { get; set; } public virtual ICollection Tenants { get; set; } // Массив ссылок на объекты типа Tenant, связанные с этим экземпляром типа Apartment. Навигационное свойство. }

Один класс, становится контейнером для другого.

Три типа загрузки

Существует три типа загрузки связанных данных:

  • отложенная (ленивая);
  • безотложная (прямая);
  • явная.

Они различаются механизмом и производительностью.

При первичной выборке не загружает никакие связанные данные. Они будут загружены только после того, как программист запустит загрузку через навигационное свойство.

Так, если мы попытаемся загрузить данные о квартире с номером 6, то данные о жильцах этой квартиры загружены не будут, это придется делать в два запроса.

Private RegistrationContext db = new RegistrationContext(); // Запрос, извлекающий из таблицы Apartments строку, где в столбце ApartNumber установлено значение 6. Apartment apartment = db.Apartments.Where(n=>n.ApartNumber == 6).FirstOrDefault(); // Второй запрос, извлекающий все объекты Tenant связанные данным объектом Apartment foreach (Tenant t in apartment.Tenants) { // Действия с данными }

Когда идет полная выборка, нам нужны два цикла (один внутри другого):

Foreach (Apartment a in db.Apartments) { foreach(Tenant t in a.Tenants) { // Как-то используем данные. } }

Класс DbContext использует ленивую загрузку по умолчанию. Однако, ленивая загрузка по умолчанию не сработает если:

  • класс модели запечатан (sealed);
  • объявлен с идентификатором доступа отличным от public;
  • навигационное свойство не объявлено виртуальным.

Любое невыполнение этих условий отключает ленивую загрузку, что можно сделать явно с помощью следующей инструкции в конструкторе класса модели:

Прямая загрузка

Apartments = db.Apartments.Include(t=>t.Tenants) foreach (Apartment a in apartments) { foreach(Tenant t in a.Tenants) { // Как-то используем данные. } }

Хотя в примере выше использованы два цикла, запрос только один.

Допустимо использовать в одной цепочке методов сколько угодно вызовов Include.

Явная загрузка

Похожа на ленивую загрузку. Работает также, но требует явного указания инструкции загрузки (метод Load). Используется если, ленивая загрузка отключена.

В отличие от ленивой, явная загрузка использует для доступа к объекту сущности не свойства контекста (DbSet), а его метод Entry().

Var apartments = db.Apartments.ToList(); foreach (Apartment a in apartments) { // Указываем откуда и что нам нужно загрузить. Конец цепочки - вызов метода Load(). db.Entry(a).Collection(t => t.Tenants).Load(); foreach(Tenant t in a.Tenants) { // Что-то делаем с данными. } }

Обратите внимание на «явность» такого вызова.

  • .db // Объект контекста.
  • .Entry(a) // В параметре объект модели.
  • .Collection(t => t.Tenants) // Метод Collection, потому что навигационное свойство содержит массив ссылок. В параметре делегат, с указанием навигационного свойства.
  • .Load(); //Явный вызов загрузки.

Какую загрузку использовать

Применяйте соответствующую загрузку, пользуясь соображениями производительности. Если вы точно знаете, какие данные нужно отобразить - используйте ленивую загрузку. Если предоставляете выбор пользователю о детальности отображаемой информации, то отложенная - идеальный вариант.

Отложенная загрузка гораздо эффективнее, если требуется контролировать каждый цикл обращений к БД. Если код представляет обработку больших объектов с несколькими навигационными свойствами в каждом, ленивая загрузка, поскольку генерирует большее количество запросов, может вызвать зависание.

Однако, универсального метода тут нет, нужно тестировать каждое приложение для разного размера базы, в том числе и с помощью модульных тестов.

Создание страницы, отображающей информацию о квартирах и проживающих.

Мы собираемся сгенерировать контроллер и GRUD представления с помощью Visual Studio. Для этого в обозревателе решений вызовите контекстное меню на папке Controllers и выберите пункт «Добавить контроллер».

Выберите пункт Контроллер MVC 5 c представлениями, использующий Entity и нажмите «Добавить».

  • класс модели (Apartment);
  • имя контроллера (ApartmentController);
  • и класс контекста (RegistrationContext)

После нажатия «Добавить» Visual Studio сгенерирует вам контроллер с методами действия соответствующим CRUD - инструкциям. Нам предстоит их только поправить.

Наша цель - это страница. Которая может отображать одновременно две таблицы: первая с данными из таблицы Apartmets, вторая - данные из таблицы Tenants, связанные с выделенным элементом из первой таблицы.

Для этого нам понадобится совокупная модель представления включающая данные как из первой, так и из второй таблицы. Cоздадим ее в папке Views/ViewsModels в файле ApartmentIndexer.cs :

Using System.Collections.Generic; using EnrollmentApp.Models; namespace EnrollmentApp.Views.ViewsModel { public class ApartmentIndexer { public IEnumerable Apartments { get; set; } // Свойство для хранения коллекции объектов типа Apartment public IEnumerable Tenants { get; set; } // Свойство для хранения коллекции объектов типа Apartment } }

Чтобы мы могли работать с предыдущим классом в ApartmentController , добавьте в него ссылку на файл:

Using EnrollmentApp.Views.ViewsModel;

Теперь отредактируем метод Index, который будет отображать информацию из двух таблиц.

Public class ApartmentController: Controller { private RegistrationContext db = new RegistrationContext(); // GET: Apartment public ActionResult Index(int? id) { // создаем наш совокупный класс. var IndexModel = new ApartmentIndexer(); // Наполняем его элементами таблицы Apartments. IndexModel.Apartments = db.Apartments .Include(t => t.Tenants) .OrderBy(t => t.Apartnumber); if (id != null) { ViewBag.ApartmentID = id.Value; // Наполняем связанную коллекцию для каждой квартиры соотвествующими жильцами.Чтобы гарантировать, что жилец будет один применяем метод Single // Альтернатива – применить SingeOrDefault IndexModel.Tenants = IndexModel.Apartments.Where(i => i.ApartmentID == id.Value).Single().Tenants; } // Передаем класс-контейнер в представление. return View(IndexModel); } }

Этот метод принимает параметр id, которые будет генерировать ссылка в представлении. Благодаря параметру id, мы можем понять, какую квартиру пользователь выбрал и вывести на экран данные связанные с ней.

Осталось исправить представление Index, добавив в него две таблицы ссылки и отобразить данные:

@model EnrollmentApp.Views.ViewsModel.ApartmentIndexer @{ ViewBag.Title = "Квартиры"; }

Index

@Html.ActionLink("Добавить квартиру", "Create")

@foreach (var item in Model.Apartments) { }
Номер квартиры Количество комнат Цена
@Html.DisplayFor(modelItem => item.Apartnumber) @Html.DisplayFor(modelItem => item.NumberofRooms) @Html.DisplayFor(modelItem => item.ApartСost) @Html.ActionLink("Выбрать","Index",new { id = item.ApartmentID}) | @Html.ActionLink("Редактировать", "Edit", new { id=item.ApartmentID }) | @Html.ActionLink("Подробности", "Details", new { id=item.ApartmentID }) | @Html.ActionLink("Удалить", "Delete", new { id=item.ApartmentID })
@if (Model.Tenants != null) {

Жители этой квартиры

@foreach (var item in Model.Tenants) { }
Фамилия Имя и Отчество Дата регистрации
@item.LastName @item.FirstAndMidName @item.RegistrationDate
}

Теперь запустив приложение, перейдите на страницу Index. Страница отображает список квартир:

Последнее обновление: 08.04.2017

Большинство операций с данными так или иначе представляют собой CRUD операции (Create, Read, Update, Delete), то есть создание, получение, обновление и удаление. Entity Framework Core позволяет легко выполнять все эти действия.

Для примера создадим проект по типу Console App (.NET Core) . И после создания проекта сразу добавим в него функциональность EF Core. Для этого в проект через NuGet пакеты Microsoft.EntityFrameworkCore.SqlServer и Microsoft.EntityFrameworkCore.Tools .

Затем добавим в проект класс User, объекты которого будут храниться в базе данных:

Public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }

И добавим класс контекста данных ApplicationContext:

Using Microsoft.EntityFrameworkCore; namespace HelloApp { public class ApplicationContext: DbContext { public DbSet Users { get; set; } public ApplicationContext() { Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=helloappdb;Trusted_Connection=True;"); } } }

Using System; using System.Linq; namespace HelloApp { public class Program { public static void Main(string args) { // Добавление using (ApplicationContext db = new ApplicationContext()) { User user1 = new User { Name = "Tom", Age = 33 }; User user2 = new User { Name = "Alice", Age = 26 }; // Добавление db.Users.Add(user1); db.Users.Add(user2); db.SaveChanges(); } // получение using (ApplicationContext db = new ApplicationContext()) { // получаем объекты из бд и выводим на консоль var users = db.Users.ToList(); Console.WriteLine("Данные после добавления:"); foreach (User u in users) { Console.WriteLine($"{u.Id}.{u.Name} - {u.Age}"); } } // Редактирование using (ApplicationContext db = new ApplicationContext()) { // получаем первый объект User user = db.Users.FirstOrDefault(); if(user!=null) { user.Name = "Bob"; user.Age = 44; //обновляем объект //db.Users.Update(user); db.SaveChanges(); } // выводим данные после обновления Console.WriteLine("\nДанные после редактирования:"); var users = db.Users.ToList(); foreach (User u in users) { Console.WriteLine($"{u.Id}.{u.Name} - {u.Age}"); } } // Удаление using (ApplicationContext db = new ApplicationContext()) { // получаем первый объект User user = db.Users.FirstOrDefault(); if (user != null) { //удаляем объект db.Users.Remove(user); db.SaveChanges(); } // выводим данные после обновления Console.WriteLine("\nДанные после удаления:"); var users = db.Users.ToList(); foreach (User u in users) { Console.WriteLine($"{u.Id}.{u.Name} - {u.Age}"); } } Console.Read(); } } }

И после выполнения мы получим следующий консольный вывод:

Данные после добавления 1.Tom - 33 2.Alice - 26 Данные после редактирования 1.Bob - 44 2.Alice - 26 Данные после удаления 2.Alice - 26

Добавление

Для добавления объекта используется метод Add , определенный у класса DbSet, в который передается добавляемый объект:

Db.Users.Add(user2); db.SaveChanges();

Метод Add устанавливает значение Added в качестве состояния нового объекта. Поэтому метод db.SaveChanges() сгенерирует выражение INSERT для вставки модели в таблицу.

Если нам надо добавить сразу несколько объектов, то мы можем воспользоваться методом AddRange() :

User user1 = new User { Name = "Tom", Age = 33 }; User user2 = new User { Name = "Alice", Age = 26 }; db.Users.AddRange(user1, user2);

Удаление

Удаление производится с помощью метода Remove :

Db.Users.Remove(user); db.SaveChanges();

Данный метод установит статус объекта в Deleted, благодаря чему Entity Framework при выполнении метода db.SaveChanges() сгенерирует SQL-выражение DELETE.

Если необходимо удалить сразу несколько объектов, то можно использовать метод RemoveRange() :

User user1 = db.Users.FirstOrDefault(); User user2 = db.Users.LastOrDefault(); db.Users.RemoveRange(user1, user2);

Редактирование

При изменении объекта Entity Framework сам отслеживает все изменения, и когда вызывается метод SaveChanges() , будет сформировано SQL-выражение UPDATE для данного объекта, которое обновит объект в базе данных.

Но надо отметить, что в данном случае действие контекста данных ограничивается пределами конструкции using. Но рассмотрим другой пример. Мы получаем объект в одном месте,а обновляем в другом. Например:

User user = null; using (ApplicationContext db = new ApplicationContext()) { // получаем объект user = db.Users.FirstOrDefault(); Console.WriteLine("Данные до редактирования:"); var users = db.Users.ToList(); foreach (User u in users) { Console.WriteLine($"{u.Id}.{u.Name} - {u.Age}"); } } //................... // Редактирование using (ApplicationContext db = new ApplicationContext()) { // Редактирование if (user != null) { user.Name = "Sam"; user.Age = 33; } db.SaveChanges(); // выводим данные после обновления Console.WriteLine("\nДанные после редактирования:"); var users = db.Users.ToList(); foreach (var u in users) { Console.WriteLine($"{u.Id}.{u.Name} - {u.Age}"); } }

Несмотря на то, что объект user не равен null, имеется в базе данных, но во втором блоке using обновления соответствующего объекта в БД не произойдет. И в этом случае нам надо использовать метод Update:

// Редактирование using (ApplicationContext db = new ApplicationContext()) { // Редактирование if (user != null) { user.Name = "Sam"; user.Age = 33; db.Users.Update(user); } db.SaveChanges(); // выводим данные после обновления Console.WriteLine("\nДанные после редактирования:"); var users = db.Users.ToList(); foreach (var u in users) { Console.WriteLine($"{u.Id}.{u.Name} - {u.Age}"); } }

При необходимости обновить одновременно несколько объектов, применяется метод UpdateRange() :

Db.Users.UpdateRange(user1, user2);

  • Перевод

Это продложение цикла статей, посвященого разработке с помощью Entity Framework и ASP.NET MVC 3. Первую главу вы можете найти по следующей ссылке: Создание модели данных Entity Framework для приложения ASP.NET MVC .

В предыдущем уроке мы создали MVC-приложение, которое умеет хранить и показывать данные с использованием Entity Framework и SQL Server Compact. В этом уроке мы рассмотрим создание и настройку CRUD (create, read, update, delete)-функциональности, которую MVC scaffolding автоматически создает для вас в контроллерах и представлениях.

Note общепринятой практикой является реализация паттерна «репозиторий» для создания слоя абстракции между контроллером и слоем доступа к данным. Но это будет потом, в поздних уроках (Implementing the Repository and Unit of Work Patterns).

В этом уроке будут созданы следующие страницы:

Создание страницы Details

На странице Details будет показываться содержимое коллекции Enrollements в HTML-таблице.

В Controllers \ StudentController . cs метод для представления Details представляет собой следующий код:

Public ViewResult Details(int id) { Student student = db.Students.Find(id); return View(student); }
Метод Find используется для извлечения одной сущности Student, соответствующей переданному в метод параметру id. Значение id берется из строки запроса находящейся на странице Details ссылки.

Откройте Views \ Student \ Details . cshtml . Каждое поле отображается хелпером DisplayFor:

LastName
@Html.DisplayFor(model => model.LastName)

Для отображения списка enrollments добавьте следующий код после поля EnrollmentDate, до закрывающего тега fieldset:

Нажмите на вкладку Students и щелкните на ссылку Details .

Создание страницы Create

В , замените код метода HttpPost Create:

Public ActionResult Create(Student student) { try { if (ModelState.IsValid) { db.Students.Add(student); db.SaveChanges(); return RedirectToAction("Index"); } } catch (DataException) { //Log the error (add a variable name after DataException) ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator."); } return View(student); }
Таким образом мы добавляем сущность Student, созданную ASP.NET MVC Model Binder в соответствующее множество сущностей и затем сохраняем изменения в базу. (Model binder – функциональность ASP.NET MVC, облегчающая работа с данными, пришедшими из формы. Model binder конвертирует данные из формы в соответствующие типы данных.NET Framework и передает в нужный метод как параметры. В данном случае, model binder инстанциирует сущность Student используя значения свойства из коллекции Form.)

Блок try-catch является единственным различием нашего варианта и того, что было автоматически создано. Если исключение, наследованное от DataException, перехватывается во время сохранения изменений, выводится стандартное сообщение об ошибке. Такие ошибки обычно вызываются чем-то внешним нежели программистской ошибкой, поэтому пользователю просто предлагается попробовать ещё раз. Код в Views \ Student \ Create . cshtml похож на код из Details . cshtml за исключением EditorFor и ValidationMessageFor, используемых для каждого поля вместо хелпера DisplayFor. Следующий код приведен для примера:

@Html.LabelFor(model => model.LastName)
@Html.EditorFor(model => model.LastName) @Html.ValidationMessageFor(model => model.LastName)

В Create . cshtml вносить изменения нет необходимости.

Нажмите на вкладку Students и на Create New .

Проверка данных включена по умолчанию. Введите имена и какую-нибудь неправильную дату и нажмите Create чтобы увидеть ошибку.

В этом случае вы видите проверку данных на клиентской стороне, реализованную с помощью JavaScript. Проверка данных на стороне сервера также реализована и, даже если проверка данных на стороне клиента пропустит плохие данные, они будут перехвачены на стороне сервера и будет выброшено исключение.

Измените дату на правильную, например, на 9/1/2005 и нажмите Create чтобы увидеть нового студента на странице Index .

Создание страницы Edit

В Controllers\StudentController.cs метод HttpGet Edit (тот, который без атрибута HttpPost) использует метод Find для извлечения выбранной сущности Student. Необходимости изменять код этого метода нет.

Замените код метода HttpPost Edit на следующий код:

Public ActionResult Edit(Student student) { try { if (ModelState.IsValid) { db.Entry(student).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } } catch (DataException) { //Log the error (add a variable name after DataException) ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator."); } return View(student); }
Код похож на то, что было в методе HttpPost Create, однако вместо добавления сущности в множество этот код устанавливает свойство сущности, определяющее, было ли оно изменено. При вызове SaveChanges свойство Modified указывает Entity Framework на необходимость создания SQL запроса для обновления записи в базе. Все столбцы записи будут обновлены, включая те, которые пользователь не трогал. Вопросы параллелизма игнорируются. (о вопросах параллелизма можно почитать в Handling Concurrency .)

Состояния сущностей и методы Attach и SaveChanges Methods

Контекст базы данных следит за синхронизацией сущностей в памяти с соответствующими записями в базе, и эта информация определяет то, что происходит при вызове метода SaveChanges. Например, при передаче новой сущности в метод Add, состояние этой сущности меняется на Added. Затем, при вызове метода SaveChanges, контекст базы данных инициирует выполнение SQL-запроса INSERT.

Состояние сущности может быть определено как:

  • Added. Сущности еще нет в базе. Метод SaveChanges инициирует выполнение запроса INSERT.
  • Unchanged. При вызове SaveChanges ничего не происходит. Данное состояние у сущности при извлечении её из базы данных.
  • Modified. Значения свойств сущности были изменены, SaveChanges выполняет запрос UPDATE.
  • Deleted. Сущность помечена к удалению, SaveChanges выполняет запрос DELETE.
  • Detached. Состояние сущности не отслеживается контекстом базы данных.
В приложении для десктопа состояние меняется автоматически. В данном типе приложений вы извлекаете сущность и изменяете значения каких-либо свойств, что приводит к изменению состояния на Modified. После вызова SaveChanges Entity Framework генерирует SQL-запрос UPDATE, обновляющий только те свойства, значения которых были изменены.

Однако в веб-приложении алгоритм нарушается, так как экземпляр контекста базы данных, извлекающий сущность, уничтожается после перезагрузки страницы. При HttpPost Edit происходит новый запрос и у вас появляется новый экземпляр контекста, поэтому необходимо вручную менять состояние сущности на Modified. После этого, при вызове SaveChanges Entity Framework обновит все столбцы записи в базе, так как контекст уже не знает о том, какие свойства конкретно были изменены.

Если вы хотите, чтобы Update изменял только отредактированные пользователем поля, вы можете каким-либо образом сохранить оригинальные значения (например, скрытыми полями формы), сделав их доступными в момент вызова HttpPost Edit. Таким образом вы сможете создать сущность Student используя оригинальные значения, вызвать метод Attach с оригинальной версией сущности, обновить значения сущности и вызвать SaveChanges. За более подробной информацией можно обратиться к материалам Add/Attach and Entity States и посту в блоге команды разработки Entity Framework Local Data .

Код в Views \ Student \ Edit . cshtml аналогичен коду в Create . cshtml , вносить изменения не надо.

Нажмите на вкладке Students и затем на ссылку Edit .

Измените значения и нажмите Save .

Создание страницы Delete

В Controllers\StudentController.cs метод HttpGet Delete использует метод Find для извлечения выбранной сущности Student, также, как и в Details и Edit ранее. Для реализации своего сообщения об ошибке при ошибке вызова SaveChanges, необходимо добавить дополнительную функциональность к методу и соответствующему представлению.

Как и в случае с операциями обновления и создания, операция удаления также нуждается в двух методах. Метод, вызываемый в ответ на GET-запрос, показывает пользователю представлению, позволяющее подтвердить или отменить удаление. Если пользователь подтверждает удаление, создаётся POST-запрос и вызывается метод HttpPost Delete.

Вам необходимо добавить блок исключений try-catch в код метода HttpPost Delete для обработки ошибок, которые могут возникнуть при обновлении базы данных. Если возникает ошибка, метод HttpPost Delete вызывает метод HttpGet Delete, передавая ему параметр, сигнализирующий об ошибке. Метод HttpGet Delete снова генерирует страницу подтверждения удаления и текстом ошибки.

Замените код метода HttpGet Delete на следующий код, позволяющий обработать ошибки:

Public ActionResult Delete(int id, bool? saveChangesError) { if (saveChangesError.GetValueOrDefault()) { ViewBag.ErrorMessage = "Unable to save changes. Try again, and if the problem persists see your system administrator."; } return View(db.Students.Find(id)); }
Этот код принимает опциональный параметр булевого типа, сигнализирующий о возникновении ошибки. Этот параметр равен null (false) после вызова HttpGet Delete и true при вызове HttpPost Delete.

Замените код метода HttpPost Delete (DeleteConfirmed) следующим кодом, совершающим удаление и обрабатывающим ошибки:

Public ActionResult DeleteConfirmed(int id) { try { Student student = db.Students.Find(id); db.Students.Remove(student); db.SaveChanges(); } catch (DataException) { //Log the error (add a variable name after DataException) return RedirectToAction("Delete", new System.Web.Routing.RouteValueDictionary { { "id", id }, { "saveChangesError", true } }); } return RedirectToAction("Index"); }
Код возвращает выбранную сущность и вызывает метод Remove, меняющий состояние сущности на Deleted. При вызове SaveChanges генерируется SQL-запрос DELETE.

Если производительность – приоритет, то можно обойтись без ненужных SQL-запросов, возвращающих запись путём замены кода, вызывающего методы Find и Remove:

Student studentToDelete = new Student() { StudentID = id }; db.Entry(studentToDelete).State = EntityState.Deleted;
Этим кодом мы инстанцируем сущность Student используя только значение первичного ключа и затем определяем состояние сущности как Deleted. Это всё, что нужно Entity Framework для удаление сущности.

Как уже упоминалось, метод HttpGet Delete не удаляет данные. Удаление данных в ответ на GET-запрос (или, также, редактирование, создание и любое другое действие с данными) создаёт брешь в безопасности. Для подробной информации смотрите ASP.NET MVC Tip #46 - Don"t use Delete Links because they create Security Holes в блоге Stephen Walther.

В Views \ Student \ Delete . cshtml добавьте следующий код между h2 и h3:

@ViewBag.ErrorMessage

Нажмите на вкладку Students и затем на ссылку Delete :

Нажмите Delete . Загрузится страница Index, уже без студента, которого мы удалили (вы увидите пример обработки кода в методе в уроке Handling Concurrency .)

Убеждаемся, что не осталось открытых подключений к базе данных

Чтобы быть уверенным, что все подключения к базе данных были правильно закрыты и ресурсы, занятые ими, освобождены, необходимо убедиться в том, что контекст уничтожается. Поэтому вы можете найти метод Dispose в конце класса контроллера StudentController в StudentController Добавить метки

I am a new SQL Server DBA, I heard of the CRUD acronym, but I do not quite understand the meaning and importance of these CRUD operations, can you please give a detailed explanation?

Solution

CRUD is the basic operations in any RDBMS, and this tip will take a detailed look at the CRUD operations in SQL Server.

What is CRUD?

CRUD means Create, Read, Update, Delete, and it can mean different things in different systems, but for SQL Server, it is commonly considered to map to the following SQL operations on table records.

CRUD SQL
C - Create Insert
R - Read Select
U - Update Update
D - Delete Delete

Here are two examples

In SQL Server 2008, there is a MERGE statement which can achieve the functions of CUD (no R). I purposely omit it here as it is not available across all SQL Server versions and also it is impossible to classify it to C or U or D.

Extending CRUD Concept

CRUD in essence seems to be DML (data manipulation language), but this concept can be extended to DDL (Data Definition Language). For example, if we consider a database as a container, we can CRUD lots of database objects, such as table, view, stored procedure and user, etc. Let’s use a table as an object, we can see the following CRUD actions.