엔터티 프레임 워크 및 연결 풀링


268

최근에 .NET 4.0 응용 프로그램에서 Entity Framework 4.0을 사용하기 시작했으며 풀링과 관련하여 몇 가지 궁금합니다.

  1. 내가 아는 연결 풀링은 ADO.NET 데이터 공급자, 내 경우에는 MS SQL 서버의 연결 풀링으로 관리됩니다. 새 엔티티 컨텍스트 ( ObjectContext) 를 인스턴스화 할 때 적용됩니다 ( 예 : 매개 변수 없음 new MyDatabaseModelEntities()?).

  2. a) 응용 프로그램에 대한 전역 엔터티 컨텍스트를 생성하거나 (예 : 하나의 정적 인스턴스) b) 주어진 각 작업 / 방법에 대해 엔터티 컨텍스트를 생성하고 노출하는 using블록 의 장점과 단점은 무엇입니까?

  3. 알아야 할 특정 시나리오에 대한 다른 권장 사항, 모범 사례 또는 일반적인 접근 방법은 무엇입니까?

답변:


369
  1. 연결 풀링은 다른 ADO.NET 응용 프로그램에서와 같이 처리됩니다. 엔티티 연결은 여전히 ​​기존 연결 문자열과 함께 기존 데이터베이스 연결을 사용합니다. 연결 문자열을 사용하지 않으려면 연결 풀링을 끌 수 있다고 생각합니다. ( ADO.NET (SQL Server 연결 풀링) 에 대해 자세히 알아보십시오 )
  2. 절대로 글로벌 컨텍스트를 사용하지 마십시오. ObjectContext는 내부적으로 아이디 맵 및 작업 단위를 포함한 여러 패턴을 구현합니다. 전역 컨텍스트 사용의 영향은 응용 프로그램 유형마다 다릅니다.
  3. 웹 애플리케이션의 경우 요청 당 단일 컨텍스트를 사용하십시오. 웹 서비스의 경우 통화 당 단일 컨텍스트를 사용하십시오. WinForms 또는 WPF 응용 프로그램에서는 양식 또는 발표자마다 단일 컨텍스트를 사용하십시오. 이 접근 방식을 사용할 수없는 특별한 요구 사항이있을 수 있지만 대부분의 상황에서는 이것으로 충분합니다.

WPF / WinForm 응용 프로그램에 대한 단일 개체 컨텍스트의 영향을 알고 싶다면이 문서를 확인 하십시오 . NHibernate Session에 관한 것이지만 아이디어는 동일합니다.

편집하다:

EF를 사용하면 기본적으로 각 엔티티가 컨텍스트 당 한 번만로드됩니다. 첫 번째 쿼리는 엔터티 인스턴스를 생성하고 내부에 저장합니다. 동일한 키를 가진 엔터티가 필요한 후속 쿼리는이 저장된 인스턴스를 반환합니다. 데이터 저장소의 값이 변경 되어도 초기 쿼리의 값이있는 엔터티를 계속받습니다. 이것을 신원 맵 패턴 이라고 합니다. 개체 컨텍스트를 강제로 개체를 다시로드 할 수 있지만 단일 공유 인스턴스를 다시로드 할 수 있습니다.

SaveChanges컨텍스트 를 호출 할 때까지 엔터티에 대한 변경 내용이 유지되지 않습니다 . 여러 엔터티에서 변경을 수행하고 한 번에 저장할 수 있습니다. 이것을 작업 단위 패턴 이라고 합니다. 저장할 수정 된 첨부 된 엔티티를 선택적으로 말할 수 없습니다.

이 두 패턴을 결합하면 흥미로운 효과가 나타납니다. 전체 애플리케이션에 대해 하나의 엔티티 인스턴스 만 있습니다. 변경 사항이 아직 지속되지 않거나 커밋되지 않은 경우에도 엔터티에 대한 변경 내용은 전체 응용 프로그램에 영향을줍니다. 대부분의 경우 이것은 원하는 것이 아닙니다. WPF 응용 프로그램에 편집 양식이 있다고 가정하십시오. 엔티티로 작업하고 있으며 복잡한 편집 (값 변경, 관련 엔티티 추가, 다른 관련 엔티티 제거 등)을 취소하기로 결정했습니다. 그러나 엔티티는 이미 공유 컨텍스트에서 수정되었습니다. 무엇을 하시겠습니까? 힌트 :에 대한 CancelChanges 또는 UndoChanges에 대해 모르겠습니다 ObjectContext.

서버 시나리오에 대해 논의 할 필요는 없다고 생각합니다. 여러 HTTP 요청 또는 웹 서비스 호출간에 단일 엔터티를 공유하기 만하면 응용 프로그램을 사용할 수 없게됩니다. 모든 요청 SaveChanges간에 단일 작업 단위를 공유하므로 모든 요청은 다른 요청에서 부분 데이터를 트리거 하고 저장할 수 있습니다. 이것은 또 다른 문제가있을 것입니다-컨텍스트 및 컨텍스트에서 사용되는 데이터베이스 연결 또는 컨텍스트에서 사용되는 데이터베이스 연결은 스레드 안전하지 않습니다.

읽기 전용 응용 프로그램의 경우에도 응용 프로그램을 쿼리 할 때마다 새로운 데이터를 원할 수 있으므로 전역 컨텍스트는 적합하지 않습니다.


답장을 보내 주셔서 감사합니다. 아마도 단일 글로벌 컨텍스트를 사용하는 것이 왜 나쁜지 자세히 설명 할 수 있습니까? 그것은 병렬 액세스를 어렵게 만듭니다. 그러나 다른 것은 무엇입니까?
Noldorin

좋아, 훨씬 명확 해 졌어, 고마워 글로벌 컨텍스트가 실제로 적절하지는 않지만 확인하기 위해 "편집 대화 상자"에 대한 단일 컨텍스트 등이 올바른 방법 일 수 있습니까? 웹 서비스 및 ASP.NET과 같은 다른 상황에서는 메서드 내의 컨텍스트가 더 의미가 있습니다. 맞습니까?
Noldorin

나는 당신의 조언을 받아 singelton을 제거했습니다. : 지금은 다른 오류 얻을 stackoverflow.com/questions/14795899/...
Elad BENDA

작업 단위 패턴을 구현하고 DbContext를 캡슐화하면 비즈니스 논리와 데이터베이스 작업이 분리되어야한다는 것을 알고 있습니다. 작업 단위 패턴을 구현하고 일부 작업에 대해서만 TransactionScope를 사용하는 방법을 이해할 수 없습니다.
Rudolf Dvoracek

4
@RudolfDvoracek : 쉽게. TransactionScope논리 자체가 트랜잭션을 정의하기 때문에 작업 단위에 속하지 않고 비즈니스 논리에 속합니다. 작업 단위는 함께 유지해야하는 항목 만 정의하지만 트랜잭션 범위를 통해 동일한 트랜잭션 내에서 작업 단위 지속성을 여러 번 사용할 수 있습니다.
Ladislav Mrnka

70

Daniel Simmons에 따르면 :

메소드가 리턴되기 전에 처리되도록 각 서비스 메소드에 대해 Using 문에 새 ObjectContext 인스턴스를 작성하십시오. 이 단계는 서비스 확장 성을 위해 중요합니다. 서비스 호출을 통해 데이터베이스 연결이 열린 상태로 유지되지 않도록하고 해당 작업이 종료 될 때 특정 작업에 사용되는 임시 상태가 가비지 수집됩니다. Entity Framework는 앱 도메인에 필요한 메타 데이터 및 기타 정보를 자동으로 캐시하고 ADO.NET은 데이터베이스 연결을 풀링하므로 매번 컨텍스트를 다시 작성하는 것이 빠른 작업입니다.

이것은 그의 포괄적 인 기사에서 온 것입니다.

http://msdn.microsoft.com/en-us/magazine/ee335715.aspx

이 조언은 HTTP 요청으로 확장되므로 ASP.NET에 유효합니다. WPF 응용 프로그램과 같은 상태 저장 팻 클라이언트 응용 프로그램은 "공유"컨텍스트의 유일한 경우 일 수 있습니다.


고마워, 그것은 매우 유익한 인용문입니다. 그러나 여전히 클라이언트 WPF 앱 등에 대해서도 공유 (전역) 컨텍스트가 적절한 지 궁금합니다. 이 경우 에도 이점이 있습니까?
Noldorin

WPF 앱의 전역 컨텍스트에는 이점이 없지만 심각한 피해는 없을 것입니다. 글로벌 컨텍스트를 구현하는 경우 요청 비율이 높은 경우 데이터베이스 연결을 수동으로 관리 (연결을 명시 적으로 종료)해야합니다.
Dave Swersky

1
권리; 그래서 본질적으로 여러 임시 컨텍스트를 사용하여 실제로 잘못 될 수는 없습니다 (연결 풀링이 발생한다는 것을 알고 있다면)? ... 단일 글로벌 컨텍스트를 사용하는 경우 이론상의 연결이 임의의 시점에서 끊어지지 않습니까?
Noldorin

1
@ Nolodrin : 연결이 "무작위로"떨어질 것이라고 생각하지 않습니다 ... 위험은 연결을 너무 오래 열어 연결 풀을 포화시킬 수 있다는 것입니다.
Dave Swersky

1
ObjectContext / DbContext 구현 IDisposable이므로 가장 짧은 시간 동안 열려 있어야합니다.
nicodemus13. 12.

12

EF6 (4,5도) 설명서에 따름 : https://msdn.microsoft.com/en-us/data/hh949853#9

9.3 요청 당 상황

Entity Framework의 컨텍스트는 최적의 성능 경험을 제공하기 위해 수명이 짧은 인스턴스로 사용됩니다 . 컨텍스트는 수명이 짧고 버려 질 것으로 예상되므로 가능한 한 매우 가볍고 메타 데이터를 재사용하도록 구현되었습니다. 웹 시나리오에서는이를 염두에두고 단일 요청 기간 동안 컨텍스트를 유지하지 않는 것이 중요합니다. 마찬가지로 웹 이외의 시나리오에서는 Entity Framework의 다양한 캐싱 수준에 대한 이해를 바탕으로 컨텍스트를 삭제해야합니다. 일반적으로 말해서, 스레드 당 컨텍스트 및 정적 컨텍스트뿐만 아니라 애플리케이션 수명 동안 컨텍스트 인스턴스를 사용하지 않아야합니다.


2
나는이 답변이 여기에 있었다는 것을 알고 있지만, 이것이 내가 엄청난 두통을 저축했다고 말해야한다. Oracle에서 EF를 사용할 때 "풀링 된 연결"오류가 발생하여 그 이유를 알 수 없습니다. dbContext를 클래스 변수로 설정하여 생성시 인스턴스화했습니다. 필요에 따라 컨텍스트를 작성하도록 변경하면 내 세상의 모든 병이 해결되었습니다. 감사합니다!
Fletchius

1

아래 코드는 새로운 데이터베이스 값으로 객체를 새로 고치는 데 도움이되었습니다. Entry (object) .Reload () 명령은 객체가 데이터베이스 값을 다시 호출하도록합니다.

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName);
DatabaseObjectContext.Entry(member).Reload();

이 컬렉션뿐만 아니라 (VB 코드) :CType(myContext, IObjectContextAdapter).ObjectContext.Refresh(RefreshMode.StoreWins,myCustomers)
Ivan Ferrer Villa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.