EntityFramework 7 및 Asp.Net 5를 사용하여 SQL 저장 프로 시저를 호출하는 방법

asp.net-core-mvc c# ef-database-first entity-framework-core sql-server

문제

지난 며칠 동안 EntityFramework 7 사용하여 Web API 컨트롤러 메서드 내부에서 Stored Procedure 를 호출하는 방법에 대한 자습서를 찾고 있습니다.

내가 겪은 모든 자습서는 다른 방식으로, 즉 Code First 접근법을 보여줍니다. 하지만 이미 데이터베이스가 있고 Web API 를 작성하는 데 사용해야합니다. 다양한 비즈니스 로직이 이미 Stored Procedures and Views로 작성되어 있으며이를 웹 API에서 소비해야합니다.

질문 1 : EF7Database First 접근법을 계속 수행하고 위와 같은 데이터베이스 객체를 사용할 수 있습니까?

다음 NuGet 명령을 사용하여 EntityFramework 6.1.3 을 패키지에 설치했습니다.

install-package EntityFramework 는 프로젝트에 버전 6.1.3을 추가하지만 즉시 오류 메시지를 표시하기 시작합니다 (아래 스크린 샷을 참조하십시오). 이 문제를 해결하는 방법에 대한 단서가 없습니다.

여기에 이미지 설명을 입력하십시오.

project.json 에서 다음과 같은 두 개의 항목을 볼 수있는 다른 테스트 프로젝트가 있습니다.

"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final", "EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc1-final",

그러나 Nu-Get 패키지 관리자를 검색 할 때이 버전을 볼 필요가 없습니다! 겨우 6.1.3이 나옵니다.

필자의 주요 목적은 이미 작성된 저장 프로 시저 및 뷰를 기존 데이터베이스에서 사용하는 것입니다.

1) ADO.Net 을 사용하고 싶지 않습니다. 오히려 EntityFramework 를 사용하여 ORM 을 사용하고 싶습니다.

2) EntityFramework 6.1.3 이 이미 Stored Procs 데이터베이스에서 Stored ProcsViews 를 호출 할 수있는 경우 오류 (스크린 샷)를 어떻게 해결할 수 있습니까?

이것을 달성하는 가장 좋은 방법은 무엇입니까?

수락 된 답변

나는 당신의 문제를 정확하게 이해하기를 바랍니다. 일부 필드가있는 일부 항목의 목록을 반환하는 데이터베이스에 기존 저장 프로 시저 (예 : dbo.spGetSomeData )가 있으며 웹 API 메서드의 데이터를 제공해야합니다.

구현 방법은 다음과 같습니다. DbContext 과 같이 DbContext 정의 할 수 있습니다.

public class MyDbContext : DbContext
{
}

appsettings.json 을 데이터베이스에 연결 문자열로 정의하는 것

{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  }
}

MyDbContextMyDbContext 에 추가하려면 Microsoft.Extensions.DependencyInjectionMyDbContext 합니다.

public class Startup
{
    // property for holding configuration
    public IConfigurationRoot Configuration { get; set; }

    public Startup(IHostingEnvironment env)
    {
        // Set up configuration sources.
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
            .AddEnvironmentVariables();
        // save the configuration in Configuration property
        Configuration = builder.Build();
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc()
            .AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<MyDbContext>(options => {
                options.UseSqlServer(Configuration["ConnectionString"]);
            });
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ...
    }
}

이제 WebApi 작업을 다음과 같이 구현할 수 있습니다.

[Route("api/[controller]")]
public class MyController : Controller
{
    public MyDbContext _context { get; set; }

    public MyController([FromServices] MyDbContext context)
    {
        _context = context;
    }

    [HttpGet]
    public async IEnumerable<object> Get()
    {
        var returnObject = new List<dynamic>();

        using (var cmd = _context.Database.GetDbConnection().CreateCommand()) {
            cmd.CommandText = "exec dbo.spGetSomeData";
            cmd.CommandType = CommandType.StoredProcedure;
            // set some parameters of the stored procedure
            cmd.Parameters.Add(new SqlParameter("@someParam",
                SqlDbType.TinyInt) { Value = 1 });

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

            var retObject = new List<dynamic>();
            using (var dataReader = await cmd.ExecuteReaderAsync())
            {
                while (await dataReader.ReadAsync())
                {
                    var dataRow = new ExpandoObject() as IDictionary<string, object>;
                    for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++) {
                        // one can modify the next line to
                        //   if (dataReader.IsDBNull(iFiled))
                        //       dataRow.Add(dataReader.GetName(iFiled), dataReader[iFiled]);
                        // if one want don't fill the property for NULL
                        // returned from the database
                        dataRow.Add(
                            dataReader.GetName(iFiled),
                            dataReader.IsDBNull(iFiled) ? null : dataReader[iFiled] // use null instead of {}
                        );
                    }

                    retObject.Add((ExpandoObject)dataRow);
                }
            }
            return retObject;
        }
    }
}

위의 코드는 exec dbo.spGetSomeData 를 사용하여 exec dbo.spGetSomeData 를 사용하여 모든 결과를 읽고 dynamic 객체에 저장합니다. api/My 에서 $.ajax 호출을하면 dbo.spGetSomeData 에서 반환 된 데이터를 얻을 수 있습니다.이 데이터는 JavaScript 코드에서 직접 사용할 수 있습니다. 위의 코드는 매우 투명합니다. dbo.spGetSomeData 가 반환하는 데이터 집합의 필드 이름은 JavaScript 코드의 속성 이름입니다. 어떠한 방식 으로든 C # 코드에서 엔터티 클래스를 관리 할 필요가 없습니다. C # 코드에는 저장 프로 시저에서 반환 된 필드의 이름이 없습니다. 따라서 dbo.spGetSomeData 의 코드를 확장 / 변경 (일부 필드의 이름을 바꾸고 새 필드를 추가하는 경우)하면 JavaScript 코드 만 조정해야하지만 C # 코드는 조정하지 않아도됩니다.


인기 답변

DbContext 에는 원하는 Database 로 연결할 수있는 Database 속성이 있습니다.

context.Database.SqlQuery<Foo>("exec [dbo].[GetFoo] @Bar = {0}", bar);

그러나 웹 API 작업에서이 작업을 수행하는 대신 컨텍스트에 메서드를 추가하거나 컨텍스트와 상호 작용하는 모든 서비스 / 저장소에 메서드를 추가 할 것을 제안합니다. 그런 다음이 메서드를 호출하면됩니다. 이상적으로 모든 SQL 항목을 한 곳에서 관리하고자합니다.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.