Подтвердить что ты не робот

Создание и доступ к хранимым процедурам с использованием ядра структуры Entity

Я внедряю базовый веб-API Asp.Net, ядро ​​структуры сущностей, первый подход базы данных с использованием Visual Studio 2017. Мне удалось создать файлы контекста и класса на основе существующей базы данных. Мне нужно получить доступ к хранимым процедурам, используя мой контекст. В более ранней версии структуры сущности было просто выбрать объекты хранимой процедуры в мастере и создать edmx, который содержит эти объекты. Затем я мог бы получить доступ к хранимым процедурам через объекты сложного типа, открытые инфраструктурой сущности. Как сделать подобное в ядре сущности. Пример поможет?

4b9b3361

Ответ 1

Первый подход к базе данных отсутствует в EF Core с файлами edmx. Вместо этого вам нужно использовать Scaffold-DbContext

Установите пакеты Nuget Microsoft.EntityFrameworkCore.Tools и Microsoft.EntityFrameworkCore.SqlServer.Design

Scaffold-DbContext "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

но это не получит ваши хранимые процедуры. Это все еще в работе, отслеживание проблемы # 245

Но чтобы выполнить хранимые процедуры, используйте метод FromSql, который выполняет запросы RAW SQL

например,

var products= context.Products
    .FromSql("EXECUTE dbo.GetProducts")
    .ToList();

Для использования с параметрами

var productCategory= "Electronics";

var product = context.Products
    .FromSql("EXECUTE dbo.GetProductByCategory {0}", productCategory)
    .ToList();

или

var productCategory= new SqlParameter("productCategory", "Electronics");

var product = context.Product
    .FromSql("EXECUTE dbo.GetProductByName  @productCategory", productCategory)
    .ToList();

Существуют определенные ограничения для выполнения запросов RAW SQL или хранимых процедур. Вы не можете использовать его для INSERT/UPDATE/DELETE. если вы хотите выполнить запросы INSERT, UPDATE, DELETE, используйте команду ExecuteSqlCommand

var categoryName = "Electronics";
dataContext.Database
           .ExecuteSqlCommand("dbo.InsertCategory @p0", categoryName);

Ответ 2

Приведенные выше примеры отлично работают при выполнении хранимой процедуры, если вы ожидаете, что результирующий набор будет таким же, как и любой уже определенный объект. Но что, если вы хотите получить набор результатов, который не поддерживается? По словам разработчиков EF Core 2, это функция, которая придет, но сегодня уже есть простое решение.

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

namespace Example.EF.Model
{
    public class Sample
    {
        public int SampleID { get; set; }
        public string SampleName { get; set; }
    }
}

Затем добавьте в свой контекст новый DBSet с вашей моделью:

public virtual DbSet<Sample> Sample { get; set; }

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

var products = _samplecontext.Sample
      .FromSql($"EXEC ReturnAllSamples {id}, {startdate}, {enddate}").ToList();

Я надеюсь, что это поможет кому угодно.

Ответ 3

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

List<Employee> employees = dbcontext.Employee
                    .FromSql("GetAllEmployees").ToList();

Но для Create, Update и Delete мы используем ExecuteSqlCommand, как показано ниже:

var employee = "Harold Javier";
dbcontext.Employee
           .ExecuteSqlCommand("InsertEmployee @emp", employee);

Ответ 4

Решение Rohith/Harold Javier/Sami предоставлено. Я хотел бы добавить, что вы можете создать отдельный проект EF6 для генерации классов С# для наборов результатов, а затем скопировать файлы в ваш проект EFCore. Если вы измените сохраненный процесс, вы можете обновить файл результатов, используя методы, описанные здесь: Хранимые процедуры и обновление EDMX

Если вам нужны соответствующие интерфейсы машинописи, вы можете установить этот генератор определения машинописи расширений VS2017: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TypeScriptDefinitionGenerator

Еще есть несколько вариантов копирования, но это менее утомительно, чем создание классов вручную.

Изменение: есть расширение VS2017 для создания dbconext https://marketplace.visualstudio.com/items?itemName=ErikEJ.EFCorePowerTools. Он не выполняет хранимые процедуры, но предоставляет пункт меню правой кнопкой мыши из проекта VS вместо командной строки Scaffold-DbContext.

Ответ 5

Мой оригинальный пост - fooobar.com/info/211200/...

Чтобы вызвать хранимую процедуру и получить результат в списке моделей в EF Core, мы должны выполнить 3 шага.

Шаг 1. Вам нужно добавить новый класс так же, как ваш класс сущности. Который должен иметь свойства со всеми столбцами в вашем SP. Например, если ваш SP возвращает два столбца с именами Id и Name, тогда ваш новый класс должен быть чем-то вроде

public class MySPModel
{
    public int Id {get; set;}
    public string Name {get; set;}
}

Шаг 2.

Затем вам нужно добавить одно свойство DbQuery в ваш класс DBContext для вашего SP.

public partial class Sonar_Health_AppointmentsContext : DbContext
{
        public virtual DbSet<Booking> Booking { get; set; } // your existing DbSets
        ...

        public virtual DbQuery<MySPModel> MySP { get; set; } // your new DbQuery
        ...
}

Шаг 3.

Теперь вы сможете позвонить и получить результат от вашего SP из вашего DBContext.

var result = await _context.Query<MySPModel>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();

Я использую универсальный UnitOfWork & Repository. Поэтому моя функция для выполнения SP -

/// <summary>
/// Execute function. Be extra care when using this function as there is a risk for SQL injection
/// </summary>
public async Task<IEnumerable<T>> ExecuteFuntion<T>(string functionName, string parameter) where T : class
{
    return await _context.Query<T>().AsNoTracking().FromSql(string.Format("EXEC {0} {1}", functionName, parameter)).ToListAsync();
}

Надеюсь, это будет полезно для кого-то !!!