Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

Создание специального класса чтения данных

Желательно, чтобы специальный класс чтения данных был обобщенным и содержал список моделей, которые нужно импортировать. Создайте в проекте

AutoLot.DAL
новую папку по имени
BulkImport
, a в ней — новый файл интерфейса
IMyDataReader.cs
, реализующего
IDataReader
, со следующим кодом:

using System.Collections.Generic;

using System.Data;

namespace AutoLot.Dal.BulkImport

{

public interface IMyDataReader<T> : IDataReader

{

List<T> Records { get; set; }

}

}

Далее

реализуйте специальный класс чтения данных. Как вы уже видели, классы чтения данных содержат много частей, отвечающих за перемещение данных. Хорошая новость в том, что для
SqlBulkCopy
придется реализовать лишь несколько из них. Создайте новый файл класса по имени
MyDataReader.cs
и добавьте в него перечисленные ниже операторы
using
:

using System;

using System.Collections.Generic;

using System.Data;

using System.Linq;

using System.Reflection;

Сделайте класс открытым и запечатанным и обеспечьте реализацию классом интерфейса

IMyDataReader
. Добавьте конструктор для принятия записей и установки свойства:

public sealed class MyDataReader<T> : IMyDataReader<T>

{

public List<T> Records { get; set; }

public MyDataReader(List<T> records)

{

Records = records;

}

}

Предложите Visual Studio или Visual Studio Code самостоятельно реализовать все методы (либо скопировать их), что даст вам отправную точку для специального класса чтения данных. В рассматриваемом сценарии потребуется реализовать лишь члены, кратко описанные в табл. 21.7.

Начните с метода

Read
, который возвращает
false
, если класс для чтения находится в конце списка, или
true
(с инкрементированием счетчика уровня класса), если конец списка еще не достигнут. Добавьте переменную уровня класса, которая будет хранить текущий индекс
List<T>
, и обновите метод
Read
, как показано ниже:

public class MyDataReader<T> : IMyDataReader<T>

{

...

private int _currentIndex = -1;

public bool Read

{

if (_currentIndex + 1 >= Records.Count)

{

return false;

}

_currentIndex++;

return true;

}

}

Каждый

метод
GetXXX
и свойство
FieldCount
требуют знания специфической модели, подлежащей загрузке. Вот как выглядит метод
GetValue
, использующий
CarViewModel
:

public object GetValue(int i)

{

Car currentRecord = Records[_currentIndex] as Car;

return i switch

{

0 => currentRecord.Id,

1 => currentRecord.MakeId,

2 => currentRecord.Color,

3 => currentRecord.PetName,

4 => currentRecord.TimeStamp,

_ => string.Empty,

};

}

База данных содержит только четыре таблицы, но это означает необходимость в наличии четырех вариаций класса чтения данных. А подумайте о реальной производственной базе данных, в которой таблиц гораздо больше!Решить проблему можно более эффективно с применением рефлексии (см. главу 17) и LINQ to Objects (см. главу 13).

Добавьте переменные

readonly
для хранения значений
PropertyInfo
модели и словарь, который будет использоваться для хранения местоположения поля и имени таблицы в SQL Server. Модифицируйте конструктор, чтобы он принимал свойства обобщенного типа и инициализировал объект
Dictionary
. Ниже показан добавленный код:

private readonly PropertyInfo[] _propertyInfos;

private readonly Dictionary<int, string> _nameDictionary;

public MyDataReader(List<T> records)

{

Records = records;

_propertyInfos = typeof(T).GetProperties;

_nameDictionary = new Dictionary<int,string>;

}

Модифицируйте конструктор, чтобы он принимал строку подключения

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

private readonly SqlConnection _connection;

private readonly string _schema;

private readonly string _tableName;

public MyDataReader(List<T> records, SqlConnection connection,

string schema, string
tableName)

{

Records = records;

_propertyInfos = typeof(T).GetProperties;

_nameDictionary = new Dictionary<int, string>;

_connection = connection;

Поделиться с друзьями: