public class Car

  {

    public int Id { get; set; }

    public string Color { get; set; }

    public int MakeId { get; set; }

    public string PetName { get; set; }

    public byte[] TimeStamp {get;set;}

  }

}

// CarViewModel.cs

namespace AutoLot.Dal.Models

{

  public class CarViewModel : Car

  {

    public string Make { get; set; }

  }

}

На заметку! Если вы не знакомы с типом данных TimeStamp в SQL Server (который отображается на byte[] в С#), то беспокоиться об этом не стоит. Просто знайте, что он используется для проверки параллелизма на уровне строк и раскрывается вместе с Entity Framework Core.

Новые классы будут применяться вскоре. 

<p id="AutBody_Root848"><strong>Добавление класса InventoryDal</strong></p>

Далее добавьте новую папку по имени DataOperations. Поместите в нее файл класса по имени InventoryDal.cs и измените класс на public. В этом классе будут определены разнообразные члены, предназначенные для взаимодействия с таблицей Inventory базы данных AutoLot. Наконец, импортируйте следующие пространства имен:

using System; 

using System.Collections.Generic;

using System.Data;

using AutoLot.Dal.Models;

using Microsoft.Data.SqlClient;

<p id="AutBody_Root849"><strong>Добавление конструкторов</strong></p>

Создайте конструктор, который принимает строковый параметр (connectionString) и присваивает его значение переменой уровня класса. Затем создайте конструктор без параметров, передающий стандартную строку подключения другому конструктору В итоге вызывающий код получит возможность изменения строки подключения, если стандартный вариант не подходит. Ниже показан соответствующий код:

namespace AuoLot.Dal.DataOperations

{

  public class InventoryDal

  {

    private readonly string _connectionString;

    public InventoryDal() : this(

      @"Data Source=.,5433;User Id=sa;Password=P@ssw0rd;

      Initial Catalog=AutoLot")

    {

    }

    public InventoryDal(string connectionString)

      => _connectionString = connectionString;

  }

}

<p id="AutBody_Root850"><strong>Открытие и закрытие подключения</strong></p>

Добавьте переменную уровня класса, которая будет хранить подключение, применяемое кодом доступа к данным. Добавьте также два метода: один для открытия подключения (OpenConnection()) и еще один для закрытия подключения (CloseConnection()). В методе CloseConnection() проверьте состояние подключения и если оно не закрыто, тогда вызовите метод Close() на объекте подключения. Вот как выглядит код:

private SqlConnection _sqlConnection = null;

private void OpenConnection()

{

  _sqlConnection = new SqlConnection

  {

    ConnectionString = _connectionString

  };

  _sqlConnection.Open();

}

private void CloseConnection()

{

  if (_sqlConnection?.State != ConnectionState.Closed)

  {

    _sqlConnection?.Close();

  }

}

Ради краткости в большинстве методов класса InventoryDal не будут применяться блоки try/catch для обработки возможных исключений, равно как не будут генерироваться специальные исключения для сообщения о разнообразных проблемах при выполнении (скажем, неправильно сформированная строка подключения). Если бы строилась библиотека доступа к данным производственного уровня, то определенно пришлось бы использовать приемы структурированной обработки исключений (как объяснялось в главе 7), чтобы учесть любые аномалии времени выполнения.

<p id="AutBody_Root851"><strong>Добавление реализации IDisposable</strong></p>

Добавьте к определению класса интерфейс IDisposable:

public class InventoryDal : IDisposable

{

  ...

}

Затем реализуйте шаблон освобождения, вызывая Dispose() на объекте SqlConnection:

bool _disposed = false;

protected virtual void Dispose(bool disposing)

{

  if (_disposed)

  {

    return;

  }

  if (disposing)

  {

    _sqlConnection.Dispose();

  }

  _disposed = true;

}

public void Dispose()

{

  Dispose(true);

  GC.SuppressFinalize(this);

}

Перейти на страницу:

Похожие книги