Выполните SP, используя Entity Framework и .net Core. - PullRequest
0 голосов
/ 03 октября 2018

Я создал проект веб-API, используя ядро ​​.net и инфраструктуру сущностей.При этом используется хранимая процедура, которая возвращает большинство свойств таблицы базы данных, определенной структурой сущностей.

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

_context.Set<TableFromSql>().FromSql("execute dbo.spr_GetValue").ToList();

Я создал другой класс модели, который определяет свойства, возвращаемые из SP (называемыйNewClass).

_context.Set<NewClass>().FromSql("execute dbo.spr_GetValue").ToList();

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

1 Ответ

0 голосов
/ 04 октября 2018

Запрос SQL должен возвращать данные для всех свойств сущности или типа запроса

Для этого ограничения он вызывается при сопоставлении результата запроса sql с Model.Он перебирает свойства в модели и пытается извлечь значения из результата запроса.Если свойства модели не существуют в query result, она выдаст ошибку.

Если вы хотите вернуть обязательные столбцы вместо всех столбцов, один из вариантов - определить возвращаемую модель как Query.

Для вашего демонстрационного кода вы можете определить это в OnModelCreating.

builder.Query<TableFromSql>();

Примечание , для этого вам необходимо убедиться, что все свойства в TableFromSql существуют в execute dbo.spr_GetValue.

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

    public static class DbContextExtensions
{
    public static List<T> RawSqlQuery<T>(this DbContext context,string query)
    {
        using (var command = context.Database.GetDbConnection().CreateCommand())
        {
            command.CommandText = query;
            command.CommandType = CommandType.Text;

            context.Database.OpenConnection();

            using (var result = command.ExecuteReader())
            {
                var entities = new List<T>();

                return DataReaderMapToList<T>(result);
            }
        }
    }
    public static List<T> DataReaderMapToList<T>(IDataReader dr)
    {
        List<T> list = new List<T>();
        T obj = default(T);
        while (dr.Read())
        {
            obj = Activator.CreateInstance<T>();
            foreach (PropertyInfo prop in obj.GetType().GetProperties())
            {
                if (ColumnExists(dr, prop.Name))
                {
                    if (!object.Equals(dr[prop.Name], DBNull.Value))
                    {

                        prop.SetValue(obj, dr[prop.Name], null);
                    }
                }
            }
            list.Add(obj);
        }
        return list;
    }
    public static bool ColumnExists(IDataReader reader, string columnName)
    {

        return reader.GetSchemaTable()
                     .Rows
                     .OfType<DataRow>()
                     .Any(row => row["ColumnName"].ToString() == columnName);
    }
}

Используйте код выше, например:

        var result = _context.RawSqlQuery<ToDoItemVM>("execute [dbo].[get_TodoItem]");
...