Generi c метод для выполнения хранимых процедур и сопоставления результата с классом DTO - PullRequest
0 голосов
/ 09 июля 2020

Я запускаю веб-приложение, которое будет работать в основном с хранимыми процедурами (SP).

Я хотел бы выделить этот вопрос: Какой подход является наилучшим для выполнения SP и сопоставления результат в пользовательский класс (DTO)? Является ли отражение плохим подходом для сопоставления?

Сначала я использую базу данных EF core 3.1.3, базу данных со всеми моими таблицами и SP. Я попробовал следующий подход, но я прочитал, что это не очень хорошо для производительности приложения, поскольку я использую отражение для сопоставления DataReader с классом.

public List<T> ExecuteStoredProcedure<T>(string storedProcedure, List<SqlParameter> parameters) where T : new()
{
        using (var command = context.Database.GetDbConnection().CreateCommand())
        {
            command.CommandText = storedProcedure;
            command.CommandType = CommandType.StoredProcedure;

            // set some parameters of the stored procedure
            foreach (var parameter in parameters)
            {
                parameter.Value = parameter.Value ?? DBNull.Value;
                command.Parameters.Add(parameter);
            }

            if (command.Connection.State != ConnectionState.Open)
                command.Connection.Open();

            using (var dataReader = command.ExecuteReader())
            {
                var entity = DataReaderMapToList<T>(dataReader);
                return entity;
            }
        }
}

private List<T> DataReaderMapToList<T>(DbDataReader dr)
{
            List<T> list = new List<T>();

            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    var obj = Activator.CreateInstance<T>();
                    foreach (PropertyInfo prop in obj.GetType().GetProperties())
                    {
                        if (dr.HasColumn(prop.Name) && !Equals(dr[prop.Name], DBNull.Value))
                        {
                            prop.SetValue(obj, dr[prop.Name], null);
                        }
                    }
                    list.Add(obj);
                }
                return list;
            }
            return new List<T>();
}

С другой стороны , Я использую EF Core для таблиц и простых запросов.

Я думал об использовании EF для выполнения SP, но не смог найти хорошего решения, чтобы сделать его универсальным c и легко отобразить.

Я открыт для разных идей. Спасибо!

1 Ответ

1 голос
/ 09 июля 2020

Используя EF, вам понадобятся классы для результатов. Вот пример, в котором я вызываю SPro c, чтобы поместить несколько строк в класс с именем Visits. Обратите внимание на порядок параметров в массиве. Если вы хотите указать параметр по имени, используйте @ Sort=@Sort:

public virtual DbSet<Visits> SP_Visits { get; set; }

            SqlParameter[] parameters = {
                new SqlParameter("DateFrom", dateFrom),
                new SqlParameter("DateTo", dateTo),
                new SqlParameter("Aggregation", aggregation),
                new SqlParameter("Sort", sort)
                    };


    return await SP_Visits.FromSqlRaw("EXECUTE dbo.sp_Visits @DateFrom, @DateTo, @Aggregation, @Sort", parameters).ToListAsync();

. Если вам нравятся закодированные классы, это простое и безопасное решение. Если вы хотите иметь что-то абсолютно динамичное c, подумайте о DataTable. вот как это работает в простом случае, когда вы отображаете таблицу значений из любого SPro c:

Вызовите свой SPro c с необходимыми параметрами и, используя SqlDataReader, выгружаете содержимое в DataTable.

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

...